From 57c3246511434f42214e113b8902af10ab9cca49 Mon Sep 17 00:00:00 2001 From: xsipewe Date: Tue, 21 Jun 2016 15:50:34 +0200 Subject: erts: Editorial changes --- erts/doc/src/absform.xml | 1299 ++++--- erts/doc/src/alt_dist.xml | 1306 ++++--- erts/doc/src/communication.xml | 67 +- erts/doc/src/crash_dump.xml | 965 +++-- erts/doc/src/driver.xml | 451 ++- erts/doc/src/driver_entry.xml | 639 ++-- erts/doc/src/epmd.xml | 444 +-- erts/doc/src/erl.xml | 2226 ++++++----- erts/doc/src/erl_dist_protocol.xml | 1972 +++++----- erts/doc/src/erl_driver.xml | 4206 +++++++++++---------- erts/doc/src/erl_ext_dist.xml | 889 +++-- erts/doc/src/erl_nif.xml | 3692 ++++++++++-------- erts/doc/src/erl_prim_loader.xml | 117 +- erts/doc/src/erl_tracer.xml | 873 +++-- erts/doc/src/erlang.xml | 7265 ++++++++++++++++++------------------ erts/doc/src/erlc.xml | 274 +- erts/doc/src/erlsrv.xml | 613 +-- erts/doc/src/erts_alloc.xml | 1101 +++--- erts/doc/src/escript.xml | 398 +- erts/doc/src/inet_cfg.xml | 437 +-- erts/doc/src/init.xml | 226 +- erts/doc/src/introduction.xml | 56 + erts/doc/src/match_spec.xml | 968 +++-- erts/doc/src/notes.xml | 8 +- erts/doc/src/part.xml | 2 +- erts/doc/src/ref_man.xml | 10 +- erts/doc/src/run_erl.xml | 257 +- erts/doc/src/start.xml | 36 +- erts/doc/src/start_erl.xml | 201 +- erts/doc/src/time_correction.xml | 284 +- erts/doc/src/tty.xml | 67 +- erts/doc/src/werl.xml | 105 +- erts/doc/src/zlib.xml | 511 +-- 33 files changed, 17154 insertions(+), 14811 deletions(-) create mode 100644 erts/doc/src/introduction.xml (limited to 'erts/doc/src') diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index 0b04f8f70e..c7f1285879 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -26,144 +26,198 @@ Arndt Jonasson Kenneth Lundin 1 - Jultomten + - 00-12-01 + 2000-12-01 A absform.xml -

-

This document describes the standard representation of parse trees for Erlang - programs as Erlang terms. This representation is known as the abstract format. - Functions dealing with such parse trees are compile:forms/[1,2] - and functions in the modules - epp, - erl_eval, - erl_lint, - erl_pp, - erl_parse, - and - io. - They are also used as input and output for parse transforms (see the module - compile).

+

This secion describes the standard representation of parse trees for Erlang + programs as Erlang terms. This representation is known as the abstract + format. Functions dealing with such parse trees are + + compile:forms/1,2 and functions in the following + modules:

+ + + + stdlib:epp + + stdlib:erl_eval + + stdlib:erl_lint + + sdlib:erl_parse + + stdlib:erl_pp + + stdlib:io + + +

The functions are also used as input and output for parse transforms (see + the compiler:compile + module.

+

We use the function Rep to denote the mapping from an Erlang source construct C to its abstract format representation R, and write - R = Rep(C). -

-

The word LINE below represents an integer, and denotes the + R = Rep(C).

+ +

The word LINE in this section represents an integer, and denotes the number of the line in the source file where the construction occurred. - Several instances of LINE in the same construction may denote + Several instances of LINE in the same construction can denote different lines.

-

Since operators are not terms in their own right, when operators are - mentioned below, the representation of an operator should be taken to + +

As operators are not terms in their own right, when operators are + mentioned below, the representation of an operator is to be taken to be the atom with a printname consisting of the same characters as the - operator. -

+ operator.

Module Declarations and Forms -

A module declaration consists of a sequence of forms that are either +

A module declaration consists of a sequence of forms, which are either function declarations or attributes.

+ - If D is a module declaration consisting of the forms - F_1, ..., F_k, then - Rep(D) = [Rep(F_1), ..., Rep(F_k)]. - If F is an attribute -export([Fun_1/A_1, ..., Fun_k/A_k]), then - Rep(F) = {attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}. - If F is an attribute -import(Mod,[Fun_1/A_1, ..., Fun_k/A_k]), then - Rep(F) = {attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}. - If F is an attribute -module(Mod), then - Rep(F) = {attribute,LINE,module,Mod}. - If F is an attribute -file(File,Line), then - Rep(F) = {attribute,LINE,file,{File,Line}}. - If F is a function declaration - Name Fc_1 ; ... ; Name Fc_k, - where each Fc_i is a function clause with a - pattern sequence of the same length Arity, then - Rep(F) = {function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}. - - If F is a function specification - -Spec Name Ft_1; ...; Ft_k, - where Spec is either the atom spec or the atom - callback, and each Ft_i is a possibly constrained - function type with an argument sequence of the same length - Arity, then Rep(F) = - {attribute,Line,Spec,{{Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}. - - If F is a function specification - -spec Mod:Name Ft_1; ...; Ft_k, - where each Ft_i is a possibly constrained - function type with an argument sequence of the same length - Arity, then Rep(F) = - {attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., Rep(Ft_k)]}}. - - If F is a record declaration - -record(Name,{V_1, ..., V_k}), - where each V_i is a record field, then Rep(F) = - {attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}. - For Rep(V), see below. - If F is a type declaration - -Type Name(V_1, ..., V_k) :: T, where - Type is either the atom type or the atom opaque, - each V_i is a variable, and T is a type, then Rep(F) = - {attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., Rep(V_k)]}}. - - If F is a wild attribute -A(T), then - Rep(F) = {attribute,LINE,A,T}. -

+ +

If D is a module declaration consisting of the forms + F_1, ..., F_k, then + Rep(D) = [Rep(F_1), ..., Rep(F_k)].

+
+ +

If F is an attribute -export([Fun_1/A_1, ..., Fun_k/A_k]), + then Rep(F) = + {attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}.

+
+ +

If F is an attribute -import(Mod,[Fun_1/A_1, ..., Fun_k/A_k]), + then Rep(F) = + {attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., + {Fun_k,A_k}]}}.

+
+ +

If F is an attribute -module(Mod), then + Rep(F) = {attribute,LINE,module,Mod}.

+
+ +

If F is an attribute -file(File,Line), then + Rep(F) = {attribute,LINE,file,{File,Line}}.

+
+ +

If F is a function declaration Name Fc_1 ; ... ; Name Fc_k, + where each Fc_i is a function clause with a pattern sequence of + the same length Arity, then Rep(F) = + {function,LINE,Name,Arity,[Rep(Fc_1), ...,Rep(Fc_k)]}.

+
+ +

If F is a function specification -Spec Name Ft_1; ...; Ft_k, + where Spec is either the atom spec or the atom + callback, and each Ft_i is a possibly constrained + function type with an argument sequence of the same length + Arity, then Rep(F) = + {attribute,Line,Spec,{{Name,Arity},[Rep(Ft_1), ..., + Rep(Ft_k)]}}.

+
+ +

If F is a function specification + -spec Mod:Name Ft_1; ...; Ft_k, where each Ft_i is a + possibly constrained function type with an argument sequence of the + same length Arity, then Rep(F) = + {attribute,Line,spec,{{Mod,Name,Arity},[Rep(Ft_1), ..., + Rep(Ft_k)]}}.

+
+ +

If F is a record declaration -record(Name,{V_1, ..., V_k}), + where each V_i is a record field, then Rep(F) = + {attribute,LINE,record,{Name,[Rep(V_1), ..., Rep(V_k)]}}. + For Rep(V), see below.

+
+ +

If F is a type declaration -Type Name(V_1, ..., V_k) :: T, + where Type is either the atom type or the atom + opaque, each V_i is a variable, and T is a type, + then Rep(F) = + {attribute,LINE,Type,{Name,Rep(T),[Rep(V_1), ..., + Rep(V_k)]}}.

+
+ +

If F is a wild attribute -A(T), then + Rep(F) = {attribute,LINE,A,T}.

+
Record Fields -

Each field in a record declaration may have an optional - explicit default initializer expression, as well as an +

Each field in a record declaration can have an optional, + explicit, default initializer expression, and an optional type.

+ - If V is A, then - Rep(V) = {record_field,LINE,Rep(A)}. - If V is A = E, - where E is an expression, then - Rep(V) = {record_field,LINE,Rep(A),Rep(E)}. - If V is A :: T, where T is a type, then Rep(V) = - {typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}. - - If V is A = E :: T, where - E is an expression and T is a type, then Rep(V) = - {typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}. + +

If V is A, then + Rep(V) = {record_field,LINE,Rep(A)}.

+
+ +

If V is A = E, where E is an expression, then + Rep(V) = {record_field,LINE,Rep(A),Rep(E)}.

+
+ +

If V is A :: T, where T is a type, then Rep(V) = + {typed_record_field,{record_field,LINE,Rep(A)},Rep(T)}.

+
+ +

If V is A = E :: T, where + E is an expression and T is a type, then Rep(V) = + {typed_record_field,{record_field,LINE,Rep(A),Rep(E)},Rep(T)}. +

- Representation of Parse Errors and End-of-file + Representation of Parse Errors and End-of-File

In addition to the representations of forms, the list that represents - a module declaration (as returned by functions in erl_parse and - epp) may contain tuples {error,E} and - {warning,W}, denoting syntactically incorrect forms and - warnings, and {eof,LINE}, denoting an end-of-stream - encountered before a complete form had been parsed.

+ a module declaration (as returned by functions in + stdlib:epp and + sdlib:erl_parse) + can contain the following:

+ + + Tuples {error,E} and {warning,W}, denoting + syntactically incorrect forms and warnings + {eof,LINE}, denoting an end-of-stream + encountered before a complete form had been parsed +
Atomic Literals

There are five kinds of atomic literals, which are represented in the - same way in patterns, expressions and guards:

+ same way in patterns, expressions, and guards:

+ - If L is an atom literal, then - Rep(L) = {atom,LINE,L}. - If L is a character literal, then - Rep(L) = {char,LINE,L}. - If L is a float literal, then - Rep(L) = {float,LINE,L}. - If L is an integer literal, then - Rep(L) = {integer,LINE,L}. - If L is a string literal consisting of the characters - C_1, ..., C_k, then - Rep(L) = {string,LINE,[C_1, ..., C_k]}. + +

If L is an atom literal, then Rep(L) = {atom,LINE,L}.

+
+ +

If L is a character literal, then Rep(L) = {char,LINE,L}.

+
+ +

If L is a float literal, then Rep(L) = {float,LINE,L}.

+
+ +

If L is an integer literal, then + Rep(L) = {integer,LINE,L}.

+
+ +

If L is a string literal consisting of the characters + C_1, ..., C_k, then + Rep(L) = {string,LINE,[C_1, ..., C_k]}.

+
-

Note that negative integer and float literals do not occur as such; they are - parsed as an application of the unary negation operator.

+ +

Notice that negative integers and float literals do not occur as such; + they are parsed as an application of the unary negation operator.

@@ -171,288 +225,424 @@

If Ps is a sequence of patterns P_1, ..., P_k, then Rep(Ps) = [Rep(P_1), ..., Rep(P_k)]. Such sequences occur as the list of arguments to a function or fun.

+

Individual patterns are represented as follows:

+ - If P is an atomic literal L, then Rep(P) = Rep(L). - If P is a bit string pattern - <<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>, where each - Size_i is an expression that can be evaluated to an integer - and each TSL_i is a type specificer list, then - Rep(P) = {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)}]}. - For Rep(TSL), see below. - An omitted Size_i is represented by default. - An omitted TSL_i is represented by default. - If P is a compound pattern P_1 = P_2, then - Rep(P) = {match,LINE,Rep(P_1),Rep(P_2)}. - If P is a cons pattern [P_h | P_t], then - Rep(P) = {cons,LINE,Rep(P_h),Rep(P_t)}. - If P is a map pattern #{A_1, ..., A_k}, where each - A_i is an association P_i_1 := P_i_2, then Rep(P) = - {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see - below. - If P is a nil pattern [], then - Rep(P) = {nil,LINE}. - If P is an operator pattern P_1 Op P_2, - where Op is a binary operator (this is either an occurrence - of ++ 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) = {op,LINE,Op,Rep(P_1),Rep(P_2)}. - If P is an operator pattern Op P_0, - where Op is a unary operator (this is an occurrence of - an expression that can be evaluated to a number at compile - time), then Rep(P) = {op,LINE,Op,Rep(P_0)}. - If P is a parenthesized pattern ( P_0 ), then - Rep(P) = Rep(P_0), - that is, parenthesized patterns cannot be distinguished from their - bodies. - If P is a record field index pattern #Name.Field, - where Field is an atom, then - Rep(P) = {record_index,LINE,Name,Rep(Field)}. - If P is a record pattern - #Name{Field_1=P_1, ..., Field_k=P_k}, - where each Field_i is an atom or _, then Rep(P) = - {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(P_k)}]}. - If P is a tuple pattern {P_1, ..., P_k}, then - Rep(P) = {tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}. - If P is a universal pattern _, then - Rep(P) = {var,LINE,'_'}. - If P is a variable pattern V, then - Rep(P) = {var,LINE,A}, - where A is an atom with a printname consisting of the same characters as - V. + +

If P is an atomic literal L, then Rep(P) = Rep(L).

+
+ +

If P is a bitstring pattern + <<P_1:Size_1/TSL_1, ..., P_k:Size_k/TSL_k>>, where each + Size_i is an expression that can be evaluated to an integer, + and each TSL_i is a type specificer list, then Rep(P) = + {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)}]}. + For Rep(TSL), see below. + An omitted Size_i is represented by default. + An omitted TSL_i is represented by default.

+
+ +

If P is a compound pattern P_1 = P_2, then Rep(P) = + {match,LINE,Rep(P_1),Rep(P_2)}.

+
+ +

If P is a cons pattern [P_h | P_t], then Rep(P) = + {cons,LINE,Rep(P_h),Rep(P_t)}.

+
+ +

If P is a map pattern #{A_1, ..., A_k}, where each + A_i is an association P_i_1 := P_i_2, then Rep(P) = + {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see below.

+
+ +

If P is a nil pattern [], then Rep(P) = + {nil,LINE}.

+
+ +

If P is an operator pattern P_1 Op P_2, where Op is a + binary operator (this is either an occurrence of ++ 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) = + {op,LINE,Op,Rep(P_1),Rep(P_2)}.

+
+ +

If P is an operator pattern Op P_0, where Op is a + unary operator (this is an occurrence of an expression that can be + evaluated to a number at compile time), then Rep(P) = + {op,LINE,Op,Rep(P_0)}.

+
+ +

If P is a parenthesized pattern ( P_0 ), then Rep(P) = + Rep(P_0), that is, parenthesized patterns cannot be + distinguished from their bodies.

+
+ +

If P is a record field index pattern #Name.Field, + where Field is an atom, then Rep(P) = + {record_index,LINE,Name,Rep(Field)}.

+
+ +

If P is a record pattern #Name{Field_1=P_1, ..., Field_k=P_k}, + where each Field_i is an atom or _, then Rep(P) = + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(P_1)}, ..., + {record_field,LINE,Rep(Field_k),Rep(P_k)}]}.

+
+ +

If P is a tuple pattern {P_1, ..., P_k}, then Rep(P) = + {tuple,LINE,[Rep(P_1), ..., Rep(P_k)]}.

+
+ +

If P is a universal pattern _, then Rep(P) = + {var,LINE,'_'}.

+ +

If P is a variable pattern V, then Rep(P) = + {var,LINE,A}, where A is an atom with a printname consisting + of the same characters as V.

+
-

Note that every pattern has the same source form as some expression, and is - represented the same way as the corresponding expression.

+ +

Notice that every pattern has the same source form as some expression, + and is represented in the same way as the corresponding expression.

Expressions -

A body B is a nonempty sequence of expressions E_1, ..., E_k, +

A body B is a non-empty sequence of expressions E_1, ..., E_k, and Rep(B) = [Rep(E_1), ..., Rep(E_k)].

-

An expression E is one of the following alternatives:

+ +

An expression E is one of the following:

+ - If E is an atomic literal L, then Rep(E) = Rep(L). - If E is a bit string comprehension - <<E_0 || Q_1, ..., Q_k>>, - where each Q_i is a qualifier, then - Rep(E) = {bc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}. - For Rep(Q), see below. - If E is a bit string constructor - <<E_1:Size_1/TSL_1, ..., E_k:Size_k/TSL_k>>, - where each Size_i is an expression and each - TSL_i is a type specificer list, then Rep(E) = - {bin,LINE,[{bin_element,LINE,Rep(E_1),Rep(Size_1),Rep(TSL_1)}, ..., {bin_element,LINE,Rep(E_k),Rep(Size_k),Rep(TSL_k)}]}. - For Rep(TSL), see below. - An omitted Size_i is represented by default. - An omitted TSL_i is represented by default. - If E is a block expression begin B end, - where B is a body, then - Rep(E) = {block,LINE,Rep(B)}. - If E is a case expression case E_0 of Cc_1 ; ... ; Cc_k end, - where E_0 is an expression and each Cc_i is a - case clause then Rep(E) = - {'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}. - If E is a catch expression catch E_0, then - Rep(E) = {'catch',LINE,Rep(E_0)}. - If E is a cons skeleton [E_h | E_t], then - Rep(E) = {cons,LINE,Rep(E_h),Rep(E_t)}. - If E is a fun expression fun Name/Arity, then - Rep(E) = {'fun',LINE,{function,Name,Arity}}. - If E is a fun expression - fun Module:Name/Arity, then Rep(E) = - {'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}. - (Before the R15 release: Rep(E) = - {'fun',LINE,{function,Module,Name,Arity}}.) - If E is a fun expression fun Fc_1 ; ... ; Fc_k end, - where each Fc_i is a function clause then Rep(E) = - {'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}. - If E is a fun expression - fun Name Fc_1 ; ... ; Name Fc_k end, - where Name is a variable and each - Fc_i is a function clause then Rep(E) = - {named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}. - - If E is a function call E_0(E_1, ..., E_k), then - Rep(E) = {call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}. - If E is a function call E_m:E_0(E_1, ..., E_k), - then Rep(E) = - {call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., Rep(E_k)]}. - - If E is an if expression if Ic_1 ; ... ; Ic_k end, - where each Ic_i is an if clause then Rep(E) = - {'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}. - If E is a list comprehension [E_0 || Q_1, ..., Q_k], - where each Q_i is a qualifier, then Rep(E) = - {lc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}. For Rep(Q), see - below. - If E is a map creation #{A_1, ..., A_k}, - where each A_i is an association E_i_1 => E_i_2 - or E_i_1 := E_i_2, then Rep(E) = - {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see - below. - If E is a map update E_0#{A_1, ..., A_k}, - where each A_i is an association E_i_1 => E_i_2 - or E_i_1 := E_i_2, then Rep(E) = - {map,LINE,Rep(E_0),[Rep(A_1), ..., Rep(A_k)]}. - For Rep(A), see below. - If E is a match operator expression P = E_0, - where P is a pattern, then - Rep(E) = {match,LINE,Rep(P),Rep(E_0)}. - If E is nil, [], then - Rep(E) = {nil,LINE}. - If E is an operator expression E_1 Op E_2, - where Op is a binary operator other than the match - operator =, then - Rep(E) = {op,LINE,Op,Rep(E_1),Rep(E_2)}. - If E is an operator expression Op E_0, - where Op is a unary operator, then - Rep(E) = {op,LINE,Op,Rep(E_0)}. - If E is a parenthesized expression ( E_0 ), then - Rep(E) = Rep(E_0), that is, parenthesized - expressions cannot be distinguished from their bodies. - If E is a receive expression receive Cc_1 ; ... ; Cc_k end, - where each Cc_i is a case clause then Rep(E) = - {'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}. - If E is a receive expression - receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end, - where each Cc_i is a case clause, - E_0 is an expression and B_t is a body, then Rep(E) = - {'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)],Rep(E_0),Rep(B_t)}. - If E is a record creation - #Name{Field_1=E_1, ..., Field_k=E_k}, - where each Field_i is an atom or _, then Rep(E) = - {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}. - If E is a record field access E_0#Name.Field, - where Field is an atom, then - Rep(E) = {record_field,LINE,Rep(E_0),Name,Rep(Field)}. - If E is a record field index #Name.Field, - where Field is an atom, then - Rep(E) = {record_index,LINE,Name,Rep(Field)}. - If E is a record update - E_0#Name{Field_1=E_1, ..., Field_k=E_k}, - where each Field_i is an atom, then Rep(E) = - {record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}. - If E is a tuple skeleton {E_1, ..., E_k}, then - Rep(E) = {tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}. - If E is a try expression try B catch Tc_1 ; ... ; Tc_k end, - where B is a body and each Tc_i is a catch clause then - Rep(E) = - {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}. - If E is a try expression - try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end, - where B is a body, - each Cc_i is a case clause and - each Tc_j is a catch clause then Rep(E) = - {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],[]}. - If E is a try expression try B after A end, - where B and A are bodies then Rep(E) = - {'try',LINE,Rep(B),[],[],Rep(A)}. - If E is a try expression - try B of Cc_1 ; ... ; Cc_k after A end, - where B and A are a bodies and - each Cc_i is a case clause then Rep(E) = - {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[],Rep(A)}. - If E is a try expression - try B catch Tc_1 ; ... ; Tc_k after A end, - where B and A are bodies and - each Tc_i is a catch clause then Rep(E) = - {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],Rep(A)}. - If E is a try expression - try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A end, - where B and A are a bodies, - each Cc_i is a case clause, and - each Tc_j is a catch clause then - Rep(E) = - {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., Rep(Tc_n)],Rep(A)}. - If E is a variable V, then Rep(E) = {var,LINE,A}, - where A is an atom with a printname consisting of the same - characters as V. + +

If E is an atomic literal L, then Rep(E) = Rep(L).

+
+ +

If E is a bitstring comprehension + <<E_0 || Q_1, ..., Q_k>>, + where each Q_i is a qualifier, then Rep(E) = + {bc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}. + For Rep(Q), see below.

+
+ +

If E is a bitstring constructor + <<E_1:Size_1/TSL_1, ..., E_k:Size_k/TSL_k>>, + where each Size_i is an expression and each + TSL_i is a type specificer list, then Rep(E) = + {bin,LINE,[{bin_element,LINE,Rep(E_1),Rep(Size_1),Rep(TSL_1)}, + ..., {bin_element,LINE,Rep(E_k),Rep(Size_k),Rep(TSL_k)}]}. + For Rep(TSL), see below. + An omitted Size_i is represented by default. + An omitted TSL_i is represented by default.

+
+ +

If E is a block expression begin B end, + where B is a body, then Rep(E) = + {block,LINE,Rep(B)}.

+
+ +

If E is a case expression case E_0 of Cc_1 ; ... ; Cc_k end, + where E_0 is an expression and each Cc_i is a + case clause, then Rep(E) = + {'case',LINE,Rep(E_0),[Rep(Cc_1), ..., Rep(Cc_k)]}.

+
+ +

If E is a catch expression catch E_0, then Rep(E) = + {'catch',LINE,Rep(E_0)}.

+
+ +

If E is a cons skeleton [E_h | E_t], then Rep(E) = + {cons,LINE,Rep(E_h),Rep(E_t)}.

+
+ +

>If E is a fun expression fun Name/Arity, then Rep(E) = + {'fun',LINE,{function,Name,Arity}}.

+
+ +

If E is a fun expression fun Module:Name/Arity, then Rep(E) = + {'fun',LINE,{function,Rep(Module),Rep(Name),Rep(Arity)}}. + (Before Erlang/OTP R15: Rep(E) = + {'fun',LINE,{function,Module,Name,Arity}}.)

+
+ +

If E is a fun expression fun Fc_1 ; ... ; Fc_k end, + where each Fc_i is a function clause, then Rep(E) = + {'fun',LINE,{clauses,[Rep(Fc_1), ..., Rep(Fc_k)]}}.

+
+ +

If E is a fun expression fun Name Fc_1 ; ... ; Name Fc_k end, + where Name is a variable and each + Fc_i is a function clause, then Rep(E) = + {named_fun,LINE,Name,[Rep(Fc_1), ..., Rep(Fc_k)]}.

+
+ +

If E is a function call E_0(E_1, ..., E_k), then Rep(E) = + {call,LINE,Rep(E_0),[Rep(E_1), ..., Rep(E_k)]}.

+
+ +

If E is a function call E_m:E_0(E_1, ..., E_k), then Rep(E) = + {call,LINE,{remote,LINE,Rep(E_m),Rep(E_0)},[Rep(E_1), ..., + Rep(E_k)]}.

+
+ +

If E is an if expression if Ic_1 ; ... ; Ic_k end, + where each Ic_i is an if clause, then Rep(E) = + {'if',LINE,[Rep(Ic_1), ..., Rep(Ic_k)]}.

+
+ +

If E is a list comprehension [E_0 || Q_1, ..., Q_k], + where each Q_i is a qualifier, then Rep(E) = + {lc,LINE,Rep(E_0),[Rep(Q_1), ..., Rep(Q_k)]}. + For Rep(Q), see below.

+
+ +

If E is a map creation #{A_1, ..., A_k}, + where each A_i is an association E_i_1 => E_i_2 + or E_i_1 := E_i_2, then Rep(E) = + {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see below.

+
+ +

If E is a map update E_0#{A_1, ..., A_k}, + where each A_i is an association E_i_1 => E_i_2 + or E_i_1 := E_i_2, then Rep(E) = + {map,LINE,Rep(E_0),[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see below.

+
+ +

If E is a match operator expression P = E_0, + where P is a pattern, then Rep(E) = + {match,LINE,Rep(P),Rep(E_0)}.

+
+ +

If E is nil, [], then Rep(E) = {nil,LINE}.

+
+ +

If E is an operator expression E_1 Op E_2, + where Op is a binary operator other than match operator + =, then Rep(E) = + {op,LINE,Op,Rep(E_1),Rep(E_2)}.

+
+ +

If E is an operator expression Op E_0, + where Op is a unary operator, then Rep(E) = + {op,LINE,Op,Rep(E_0)}.

+
+ +

If E is a parenthesized expression ( E_0 ), then Rep(E) = + Rep(E_0), that is, parenthesized expressions cannot be + distinguished from their bodies.

+
+ +

If E is a receive expression receive Cc_1 ; ... ; Cc_k end, + where each Cc_i is a case clause, then Rep(E) = + {'receive',LINE,[Rep(Cc_1), ..., Rep(Cc_k)]}.

+
+ +

If E is a receive expression + receive Cc_1 ; ... ; Cc_k after E_0 -> B_t end, + where each Cc_i is a case clause, E_0 is an expression, + and B_t is a body, then Rep(E) = + {'receive',LINE,[Rep(Cc_1), ..., + Rep(Cc_k)],Rep(E_0),Rep(B_t)}.

+
+ +

If E is a record creation + #Name{Field_1=E_1, ..., Field_k=E_k}, + where each Field_i is an atom or _, then Rep(E) = + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}.

+
+ +

If E is a record field access E_0#Name.Field, + where Field is an atom, then Rep(E) = + {record_field,LINE,Rep(E_0),Name,Rep(Field)}.

+
+ +

If E is a record field index #Name.Field, + where Field is an atom, then Rep(E) = + {record_index,LINE,Name,Rep(Field)}.

+ +

If E is a record update + E_0#Name{Field_1=E_1, ..., Field_k=E_k}, + where each Field_i is an atom, then Rep(E) = + {record,LINE,Rep(E_0),Name,[{record_field,LINE,Rep(Field_1),Rep(E_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(E_k)}]}.

+
+ +

If E is a tuple skeleton {E_1, ..., E_k}, then Rep(E) = + {tuple,LINE,[Rep(E_1), ..., Rep(E_k)]}.

+
+ +

If E is a try expression try B catch Tc_1 ; ... ; Tc_k end, + where B is a body and each Tc_i is a catch clause, + then Rep(E) = + {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., Rep(Tc_k)],[]}.

+
+ +

If E is a try expression + try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n end, + where B is a body, each Cc_i is a case clause, and + each Tc_j is a catch clause, then Rep(E) = + {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., + Rep(Tc_n)],[]}.

+
+ +

If E is a try expression try B after A end, + where B and A are bodies, then Rep(E) = + {'try',LINE,Rep(B),[],[],Rep(A)}.

+
+ +

If E is a try expression + try B of Cc_1 ; ... ; Cc_k after A end, + where B and A are a bodies, + and each Cc_i is a case clause, then Rep(E) = + {'try',LINE,Rep(B),[Rep(Cc_1), ..., + Rep(Cc_k)],[],Rep(A)}.

+
+ +

If E is a try expression + try B catch Tc_1 ; ... ; Tc_k after A end, + where B and A are bodies, + and each Tc_i is a catch clause, then Rep(E) = + {'try',LINE,Rep(B),[],[Rep(Tc_1), ..., + Rep(Tc_k)],Rep(A)}.

+
+ +

If E is a try expression + try B of Cc_1 ; ... ; Cc_k catch Tc_1 ; ... ; Tc_n after A + end, where B and A are a bodies, + each Cc_i is a case clause, + and each Tc_j is a catch clause, then Rep(E) = + {'try',LINE,Rep(B),[Rep(Cc_1), ..., Rep(Cc_k)],[Rep(Tc_1), ..., + Rep(Tc_n)],Rep(A)}.

+
+ +

If E is a variable V, then Rep(E) = {var,LINE,A}, + where A is an atom with a printname consisting of the same + characters as V.

+
Qualifiers -

A qualifier Q is one of the following alternatives:

+

A qualifier Q is one of the following:

+ - If Q is a filter E, where E is an expression, then - Rep(Q) = Rep(E). - If Q is a generator P <- E, where P is - a pattern and E is an expression, then - Rep(Q) = {generate,LINE,Rep(P),Rep(E)}. - If Q is a bit string generator - P <= E, where P is - a pattern and E is an expression, then - Rep(Q) = {b_generate,LINE,Rep(P),Rep(E)}. + +

If Q is a filter E, where E is an expression, then + Rep(Q) = Rep(E).

+
+ +

If Q is a generator P <- E, where P is + a pattern and E is an expression, then Rep(Q) = + {generate,LINE,Rep(P),Rep(E)}.

+
+ +

If Q is a bitstring generator P <= E, where P is + a pattern and E is an expression, then Rep(Q) = + {b_generate,LINE,Rep(P),Rep(E)}.

+
- Bit String Element Type Specifiers -

A type specifier list TSL for a bit string element is a sequence + Bitstring Element Type Specifiers +

A type specifier list TSL for a bitstring element is a sequence of type specifiers TS_1 - ... - TS_k, and Rep(TSL) = [Rep(TS_1), ..., Rep(TS_k)].

+ - If TS is a type specifier A, where A is an atom, - then Rep(TS) = A. - If TS is a type specifier A:Value, - where A is an atom and Value is an integer, - then Rep(TS) = {A,Value}. + +

If TS is a type specifier A, where A is an atom, + then Rep(TS) = A.

+
+ +

If TS is a type specifier A:Value, + where A is an atom and Value is an integer, + then Rep(TS) = {A,Value}.

+
Associations -

An association A is one of the following alternatives:

+

An association A is one of the following:

+ - If A is an association K => V, - then Rep(A) = {map_field_assoc,LINE,Rep(K),Rep(V)}. - - If A is an association K := V, - then Rep(A) = {map_field_exact,LINE,Rep(K),Rep(V)}. - + +

If A is an association K => V, + then Rep(A) = {map_field_assoc,LINE,Rep(K),Rep(V)}.

+
+ +

If A is an association K := V, + then Rep(A) = {map_field_exact,LINE,Rep(K),Rep(V)}.

+
Clauses -

There are function clauses, if clauses, case clauses +

There are function clauses, if clauses, case clauses, and catch clauses.

-

A clause C is one of the following alternatives:

+ +

A clause C is one of the following:

+ - If C is a case clause P -> B, - where P is a pattern and B is a body, then - Rep(C) = {clause,LINE,[Rep(P)],[],Rep(B)}. - If C is a case clause P when Gs -> B, - where P is a pattern, - Gs is a guard sequence and B is a body, then - Rep(C) = {clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}. - If C is a catch clause P -> B, - where P is a pattern and B is a body, then - Rep(C) = {clause,LINE,[Rep({throw,P,_})],[],Rep(B)}. - If C is a catch clause X : P -> B, - where X is an atomic literal or a variable pattern, - P is a pattern, and B is a body, then - Rep(C) = {clause,LINE,[Rep({X,P,_})],[],Rep(B)}. - If C is a catch clause P when Gs -> B, - where P is a pattern, Gs is a guard sequence, - and B is a body, then - Rep(C) = {clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}. - If C is a catch clause X : P when Gs -> B, - where X is an atomic literal or a variable pattern, - P is a pattern, Gs is a guard sequence, - and B is a body, then - Rep(C) = {clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}. - If C is a function clause ( Ps ) -> B, - where Ps is a pattern sequence and B is a body, then - Rep(C) = {clause,LINE,Rep(Ps),[],Rep(B)}. - If C is a function clause ( Ps ) when Gs -> B, - where Ps is a pattern sequence, - Gs is a guard sequence and B is a body, then - Rep(C) = {clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}. - If C is an if clause Gs -> B, - where Gs is a guard sequence and B is a body, then - Rep(C) = {clause,LINE,[],Rep(Gs),Rep(B)}. + +

If C is a case clause P -> B, + where P is a pattern and B is a body, then + Rep(C) = {clause,LINE,[Rep(P)],[],Rep(B)}.

+
+ +

If C is a case clause P when Gs -> B, + where P is a pattern, + Gs is a guard sequence, and B is a body, then + Rep(C) = {clause,LINE,[Rep(P)],Rep(Gs),Rep(B)}.

+
+ +

If C is a catch clause P -> B, + where P is a pattern and B is a body, then + Rep(C) = {clause,LINE,[Rep({throw,P,_})],[],Rep(B)}.

+
+ +

If C is a catch clause X : P -> B, + where X is an atomic literal or a variable pattern, + P is a pattern, and B is a body, then + Rep(C) = {clause,LINE,[Rep({X,P,_})],[],Rep(B)}.

+
+ +

If C is a catch clause P when Gs -> B, + where P is a pattern, Gs is a guard sequence, + and B is a body, then + Rep(C) = {clause,LINE,[Rep({throw,P,_})],Rep(Gs),Rep(B)}.

+
+ +

If C is a catch clause X : P when Gs -> B, + where X is an atomic literal or a variable pattern, + P is a pattern, Gs is a guard sequence, + and B is a body, then + Rep(C) = {clause,LINE,[Rep({X,P,_})],Rep(Gs),Rep(B)}.

+
+ +

If C is a function clause ( Ps ) -> B, + where Ps is a pattern sequence and B is a body, then + Rep(C) = {clause,LINE,Rep(Ps),[],Rep(B)}.

+
+ +

If C is a function clause ( Ps ) when Gs -> B, + where Ps is a pattern sequence, + Gs is a guard sequence and B is a body, then + Rep(C) = {clause,LINE,Rep(Ps),Rep(Gs),Rep(B)}.

+
+ +

If C is an if clause Gs -> B, + where Gs is a guard sequence and B is a body, then + Rep(C) = {clause,LINE,[],Rep(Gs),Rep(B)}.

+
@@ -460,205 +650,292 @@ Guards

A guard sequence Gs is a sequence of guards G_1; ...; G_k, and Rep(Gs) = [Rep(G_1), ..., Rep(G_k)]. If the guard sequence is - empty, Rep(Gs) = [].

-

A guard G is a nonempty sequence of guard tests + empty, then Rep(Gs) = [].

+ +

A guard G is a non-empty sequence of guard tests Gt_1, ..., Gt_k, and Rep(G) = [Rep(Gt_1), ..., Rep(Gt_k)].

-

A guard test Gt is one of the following alternatives:

+ +

A guard test Gt is one of the following:

+ - If Gt is an atomic literal L, then Rep(Gt) = Rep(L). - If Gt is a bit string constructor - <<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>, - where each Size_i is a guard test and each - TSL_i is a type specificer list, then - Rep(Gt) = {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)}]}. - For Rep(TSL), see above. - An omitted Size_i is represented by default. - An omitted TSL_i is represented by default. - If Gt is a cons skeleton [Gt_h | Gt_t], then - Rep(Gt) = {cons,LINE,Rep(Gt_h),Rep(Gt_t)}. - If Gt is a function call A(Gt_1, ..., Gt_k), - where A is an atom, then Rep(Gt) = - {call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}. - If Gt is a function call A_m:A(Gt_1, ..., Gt_k), - where A_m is the atom erlang and A is - an atom or an operator, then Rep(Gt) = - {call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., Rep(Gt_k)]}. - If Gt is a map creation #{A_1, ..., A_k}, - where each A_i is an association Gt_i_1 => Gt_i_2 - or Gt_i_1 := Gt_i_2, then Rep(Gt) = - {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. For Rep(A), see - above. - If Gt is a map update Gt_0#{A_1, ..., A_k}, where each - A_i is an association Gt_i_1 => Gt_i_2 - or Gt_i_1 := Gt_i_2, then Rep(Gt) = - {map,LINE,Rep(Gt_0),[Rep(A_1), ..., Rep(A_k)]}. - For Rep(A), see above. - If Gt is nil, [], - then Rep(Gt) = {nil,LINE}. - If Gt is an operator guard test Gt_1 Op Gt_2, - where Op is a binary operator other than the match - operator =, then - Rep(Gt) = {op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}. - If Gt is an operator guard test Op Gt_0, - where Op is a unary operator, then - Rep(Gt) = {op,LINE,Op,Rep(Gt_0)}. - If Gt is a parenthesized guard test ( Gt_0 ), then - Rep(Gt) = Rep(Gt_0), that is, parenthesized - guard tests cannot be distinguished from their bodies. - If Gt is a record creation - #Name{Field_1=Gt_1, ..., Field_k=Gt_k}, - where each Field_i is an atom or _, then Rep(Gt) = - {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}. - If Gt is a record field access Gt_0#Name.Field, - where Field is an atom, then - Rep(Gt) = {record_field,LINE,Rep(Gt_0),Name,Rep(Field)}. - If Gt is a record field index #Name.Field, - where Field is an atom, then - Rep(Gt) = {record_index,LINE,Name,Rep(Field)}. - If Gt is a tuple skeleton {Gt_1, ..., Gt_k}, then - Rep(Gt) = {tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}. - If Gt is a variable pattern V, then - Rep(Gt) = {var,LINE,A}, where A is an atom with - a printname consisting of the same characters as V. + +

If Gt is an atomic literal L, then Rep(Gt) = Rep(L).

+
+ +

If Gt is a bitstring constructor + <<Gt_1:Size_1/TSL_1, ..., Gt_k:Size_k/TSL_k>>, + where each Size_i is a guard test and each + TSL_i is a type specificer list, then Rep(Gt) = + {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)}]}. + For Rep(TSL), see above. + An omitted Size_i is represented by default. + An omitted TSL_i is represented by default.

+
+ +

If Gt is a cons skeleton [Gt_h | Gt_t], then Rep(Gt) = + {cons,LINE,Rep(Gt_h),Rep(Gt_t)}.

+
+ +

If Gt is a function call A(Gt_1, ..., Gt_k), + where A is an atom, then Rep(Gt) = + {call,LINE,Rep(A),[Rep(Gt_1), ..., Rep(Gt_k)]}.

+
+ +

If Gt is a function call A_m:A(Gt_1, ..., Gt_k), + where A_m is the atom erlang and A is + an atom or an operator, then Rep(Gt) = + {call,LINE,{remote,LINE,Rep(A_m),Rep(A)},[Rep(Gt_1), ..., + Rep(Gt_k)]}.

+
+ +

If Gt is a map creation #{A_1, ..., A_k}, + where each A_i is an association Gt_i_1 => Gt_i_2 + or Gt_i_1 := Gt_i_2, then Rep(Gt) = + {map,LINE,[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see above.

+
+ +

If Gt is a map update Gt_0#{A_1, ..., A_k}, + where each A_i is an association Gt_i_1 => Gt_i_2 + or Gt_i_1 := Gt_i_2, then Rep(Gt) = + {map,LINE,Rep(Gt_0),[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see above.

+
+ +

If Gt is nil, [], then Rep(Gt) = {nil,LINE}.

+
+ +

If Gt is an operator guard test Gt_1 Op Gt_2, + where Op is a binary operator other than match + operator =, then Rep(Gt) = + {op,LINE,Op,Rep(Gt_1),Rep(Gt_2)}.

+
+ +

If Gt is an operator guard test Op Gt_0, + where Op is a unary operator, then Rep(Gt) = + {op,LINE,Op,Rep(Gt_0)}.

+
+ +

If Gt is a parenthesized guard test ( Gt_0 ), then Rep(Gt) = + Rep(Gt_0), that is, parenthesized + guard tests cannot be distinguished from their bodies.

+
+ +

If Gt is a record creation + #Name{Field_1=Gt_1, ..., Field_k=Gt_k}, + where each Field_i is an atom or _, then Rep(Gt) = + {record,LINE,Name,[{record_field,LINE,Rep(Field_1),Rep(Gt_1)}, + ..., {record_field,LINE,Rep(Field_k),Rep(Gt_k)}]}.

+
+ +

If Gt is a record field access Gt_0#Name.Field, + where Field is an atom, then Rep(Gt) = + {record_field,LINE,Rep(Gt_0),Name,Rep(Field)}.

+
+ +

If Gt is a record field index #Name.Field, + where Field is an atom, then Rep(Gt) = + {record_index,LINE,Name,Rep(Field)}.

+
+ +

If Gt is a tuple skeleton {Gt_1, ..., Gt_k}, then Rep(Gt) = + {tuple,LINE,[Rep(Gt_1), ..., Rep(Gt_k)]}.

+
+ +

If Gt is a variable pattern V, then Rep(Gt) = + {var,LINE,A}, where A is an atom with + a printname consisting of the same characters as V.

+
-

Note that every guard test has the same source form as some expression, - and is represented the same way as the corresponding expression.

+ +

Notice that every guard test has the same source form as some expression, + and is represented in the same way as the corresponding expression.

Types - If T is an annotated type A :: T_0, - where A is a variable, then Rep(T) = - {ann_type,LINE,[Rep(A),Rep(T_0)]}. - If T is an atom or integer literal L, then Rep(T) = Rep(L). - - If T is a bit string type <<_:M,_:_*N>>, - where M and N are singleton integer types, then Rep(T) = - {type,LINE,binary,[Rep(M),Rep(N)]}. - If T is the empty list type [], then Rep(T) = - {type,Line,nil,[]}. - If T is a fun type fun(), then Rep(T) = - {type,LINE,'fun',[]}. - If T is a fun type fun((...) -> T_0), then - Rep(T) = {type,LINE,'fun',[{type,LINE,any},Rep(T_0)]}. - - If T is a fun type fun(Ft), where - Ft is a function type, - then Rep(T) = Rep(Ft). For Rep(Ft), see below. - If T is an integer range type L .. H, - where L and H are singleton integer types, then - Rep(T) = {type,LINE,range,[Rep(L),Rep(H)]}. - If T is a map type map(), then Rep(T) = - {type,LINE,map,any}. - If T is a map type #{A_1, ..., A_k}, where each - A_i is an association type, then Rep(T) = - {type,LINE,map,[Rep(A_1), ..., Rep(A_k)]}. - For Rep(A), see below. - If T is an operator type T_1 Op T_2, - where Op is a binary operator (this is an occurrence of - an expression that can be evaluated to an integer at compile - time), then - Rep(T) = {op,LINE,Op,Rep(T_1),Rep(T_2)}. - If T is an operator type Op T_0, where Op is a - unary operator (this is an occurrence of - an expression that can be evaluated to an integer at compile time), - then Rep(T) = {op,LINE,Op,Rep(T_0)}. - If T is ( T_0 ), then Rep(T) = Rep(T_0), - that is, parenthesized types cannot be distinguished from their - bodies. - If T is a predefined (or built-in) type N(T_1, ..., T_k), - then Rep(T) = - {type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}. - If T is a record type #Name{F_1, ..., F_k}, - where each F_i is a record field type, then Rep(T) = - {type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}. - For Rep(F), see below. - If T is a remote type M:N(T_1, ..., T_k), then Rep(T) = - {remote_type,LINE,[Rep(M),Rep(N),[Rep(T_1), ..., Rep(T_k)]]}. - - If T is a tuple type tuple(), then Rep(T) = - {type,LINE,tuple,any}. - If T is a tuple type {T_1, ..., T_k}, then Rep(T) = - {type,LINE,tuple,[Rep(T_1), ..., Rep(T_k)]}. - If T is a type union T_1 | ... | T_k, then Rep(T) = - {type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}. - If T is a type variable V, then Rep(T) = - {var,LINE,A}, where A is an atom with a printname - consisting of the same characters as V. A type variable - is any variable except underscore (_). - If T is a user-defined type N(T_1, ..., T_k), - then Rep(T) = - {user_type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}. + +

If T is an annotated type A :: T_0, + where A is a variable, then Rep(T) = + {ann_type,LINE,[Rep(A),Rep(T_0)]}.

+
+ +

If T is an atom or integer literal L, then Rep(T) = Rep(L).

+
+ +

If T is a bitstring type <<_:M,_:_*N>>, + where M and N are singleton integer types, then Rep(T) = + {type,LINE,binary,[Rep(M),Rep(N)]}.

+
+ +

If T is the empty list type [], then Rep(T) = + {type,Line,nil,[]}.

+
+ +

If T is a fun type fun(), then Rep(T) = + {type,LINE,'fun',[]}.

+
+ +

If T is a fun type fun((...) -> T_0), then Rep(T) = + {type,LINE,'fun',[{type,LINE,any},Rep(T_0)]}.

+
+ +

If T is a fun type fun(Ft), where + Ft is a function type, then Rep(T) = Rep(Ft). + For Rep(Ft), see below.

+
+ +

If T is an integer range type L .. H, + where L and H are singleton integer types, then Rep(T) = + {type,LINE,range,[Rep(L),Rep(H)]}.

+
+ +

If T is a map type map(), then Rep(T) = + {type,LINE,map,any}.

+
+ +

If T is a map type #{A_1, ..., A_k}, where each + A_i is an association type, then Rep(T) = + {type,LINE,map,[Rep(A_1), ..., Rep(A_k)]}. + For Rep(A), see below.

+
+ +

If T is an operator type T_1 Op T_2, + where Op is a binary operator (this is an occurrence of + an expression that can be evaluated to an integer at compile + time), then Rep(T) = + {op,LINE,Op,Rep(T_1),Rep(T_2)}.

+
+ +

If T is an operator type Op T_0, where Op is a + unary operator (this is an occurrence of an expression that can + be evaluated to an integer at compile time), then Rep(T) = + {op,LINE,Op,Rep(T_0)}.

+
+ +

If T is ( T_0 ), then Rep(T) = Rep(T_0), that is, + parenthesized types cannot be distinguished from their bodies.

+
+ +

If T is a predefined (or built-in) type N(T_1, ..., T_k), + then Rep(T) = {type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}.

+
+ +

If T is a record type #Name{F_1, ..., F_k}, + where each F_i is a record field type, then Rep(T) = + {type,LINE,record,[Rep(Name),Rep(F_1), ..., Rep(F_k)]}. + For Rep(F), see below.

+
+ +

If T is a remote type M:N(T_1, ..., T_k), then Rep(T) = + {remote_type,LINE,[Rep(M),Rep(N),[Rep(T_1), ..., + Rep(T_k)]]}.

+
+ +

If T is a tuple type tuple(), then Rep(T) = + {type,LINE,tuple,any}.

+
+ +

If T is a tuple type {T_1, ..., T_k}, then Rep(T) = + {type,LINE,tuple,[Rep(T_1), ..., Rep(T_k)]}.

+
+ +

If T is a type union T_1 | ... | T_k, then Rep(T) = + {type,LINE,union,[Rep(T_1), ..., Rep(T_k)]}.

+
+ +

If T is a type variable V, then Rep(T) = + {var,LINE,A}, where A is an atom with a printname + consisting of the same characters as V. A type variable + is any variable except underscore (_).

+
+ +

If T is a user-defined type N(T_1, ..., T_k), then Rep(T) = + {user_type,LINE,N,[Rep(T_1), ..., Rep(T_k)]}.

+
Function Types -

A function type Ft is one of the following alternatives:

+

A function type Ft is one of the following:

+ - If Ft is a constrained function type Ft_1 when Fc, - where Ft_1 is a function type and - Fc is a function constraint, then Rep(T) = - {type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}. - For Rep(Fc), see below. - If Ft is a function type (T_1, ..., T_n) -> T_0, - where each T_i is a type, then - Rep(Ft) = {type,LINE,'fun',[{type,LINE,product,[Rep(T_1), - ..., Rep(T_n)]},Rep(T_0)]}. + +

If Ft is a constrained function type Ft_1 when Fc, + where Ft_1 is a function type and + Fc is a function constraint, then Rep(T) = + {type,LINE,bounded_fun,[Rep(Ft_1),Rep(Fc)]}. + For Rep(Fc), see below.

+
+ +

If Ft is a function type (T_1, ..., T_n) -> T_0, + where each T_i is a type, then Rep(Ft) = + {type,LINE,'fun',[{type,LINE,product,[Rep(T_1), ..., + Rep(T_n)]},Rep(T_0)]}.

+
Function Constraints -

A function constraint Fc is a nonempty sequence of constraints - C_1, ..., C_k, and - Rep(Fc) = [Rep(C_1), ..., Rep(C_k)].

+

A function constraint Fc is a non-empty sequence of constraints + C_1, ..., C_k, and + Rep(Fc) = [Rep(C_1), ..., Rep(C_k)].

+ - If C is a constraint is_subtype(V, T) or V :: T, - where V is a type variable and T is a type, then - Rep(C) = {type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(V),Rep(T)]]}. - + If C is a constraint is_subtype(V, T) or V :: T, + where V is a type variable + and T is a type, then Rep(C) = + {type,LINE,constraint,[{atom,LINE,is_subtype},[Rep(V),Rep(T)]]}. +
Association Types - If A is an association type K => V, where - K and V are types, then Rep(A) = - {type,LINE,map_field_assoc,[Rep(K),Rep(V)]}. - If A is an association type K := V, where - K and V are types, then Rep(A) = - {type,LINE,map_field_exact,[Rep(K),Rep(V)]}. + +

If A is an association type K => V, + where K and V are types, then Rep(A) = + {type,LINE,map_field_assoc,[Rep(K),Rep(V)]}.

+
+ +

If A is an association type K := V, + where K and V are types, then Rep(A) = + {type,LINE,map_field_exact,[Rep(K),Rep(V)]}.

+
Record Field Types - If F is a record field type Name :: Type, - where Type is a type, then Rep(F) = - {type,LINE,field_type,[Rep(Name),Rep(Type)]}. + If F is a record field type Name :: Type, + where Type is a type, then Rep(F) = + {type,LINE,field_type,[Rep(Name),Rep(Type)]}. +
- The Abstract Format After Preprocessing -

The compilation option debug_info can be given to the + The Abstract Format after Preprocessing +

The compilation option debug_info can be specified to the compiler to have the abstract code stored in - the abstract_code chunk in the BEAM file + the abstract_code chunk in the Beam file (for debugging purposes).

-

In OTP R9C and later, the abstract_code chunk will - contain

-

{raw_abstract_v1,AbstractCode}

-

where AbstractCode is the abstract code as described - in this document.

-

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 abstract_v1 (R7B) or abstract_v2 - (R8B).

+ +

As from Erlang/OTP R9C, the abstract_code chunk contains + {raw_abstract_v1,AbstractCode}, where AbstractCode is the + abstract code as described in this section.

+ +

In OTP releases before R9C, the abstract code after some more + processing was stored in the Beam file. The first element of the + tuple would be either abstract_v1 (in OTP R7B) or + abstract_v2 (in OTP R8B).

diff --git a/erts/doc/src/alt_dist.xml b/erts/doc/src/alt_dist.xml index e283acc1b4..67d30a03c2 100644 --- a/erts/doc/src/alt_dist.xml +++ b/erts/doc/src/alt_dist.xml @@ -22,7 +22,8 @@ - How to implement an alternative carrier for the Erlang distribution + How to Implement an Alternative Carrier for the Erlang Distribution + Patrik Nyblom @@ -32,203 +33,271 @@ PA2 alt_dist.xml -

This document describes how one can implement ones own carrier +

This section describes how to implement an 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.

-

The document is a step by step explanation of the example - application (seated in the kernel applications directory). - The 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.

-

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 - erl_driver, and the - driver_entry documentation. -

+ carried by TCP/IP. Here is explained a method for replacing TCP/IP + with another protocol.

+ +

The section is a step-by-step explanation of the + example application (in the + Kernel application directory). The + application implements distribution over Unix + domain sockets and is written for the Sun Solaris 2 operating environment. + The mechanisms are however general and apply to any operating system Erlang + runs on. The reason the C code is not made portable, is simply + readability.

+ + +

This section was written a long time ago. Most of it is still + valid, but some things have changed since then. + Most notably is the driver interface. Some updates have been made + to the documentation of the driver presented here, + but more can be done and is planned for the future. + The reader is encouraged to read the + erl_driver and + driver_entry + documentation also.

+
Introduction -

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 has 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.

-

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.

-

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 . The easiest path is to - mimic the and 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.

-

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 (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, , that - will do most of the hard work of handling handshakes, cookies, - timers and ticking. Using makes implementing a - distribution module much easier and that's what we are doing in - the example application.

-

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 module or to any modules not - loaded at boot-time (i.e. only , and the - application itself can be used).

+

To implement a new carrier for the Erlang distribution, the main + steps are as follows.

+ +
+ Writing an Erlang Driver +

First, the protocol must be available to the Erlang machine, which + involves writing an Erlang driver. A port program cannot be used, + an Erlang driver is required. Erlang drivers can be:

+ + + +

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

+
+
+ +

Writing an Erlang driver is not easy. The driver is written + as some callback functions called by the Erlang emulator when + data is sent to the driver, or the driver has any data available on + a file descriptor. As the driver callback routines execute in the main + thread of the Erlang machine, the callback functions can perform + no blocking activity whatsoever. The callbacks are only to set up + file descriptors for waiting and/or read/write available data. All + I/O must be non-blocking. Driver callbacks are however executed + in sequence, why a global state can safely be updated within the + routines.

+
+ +
+ Writing an Erlang Interface for the Driver +

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 .

+ +

The easiest path + is to mimic the and + interfaces, but not much + functionality in those modules needs to be implemented. In the + example application, only a few of the usual interfaces are + implemented, and they are much simplified.

+
+ +
+ Writing a Distribution Module +

When the protocol is available to Erlang through a driver and an + Erlang interface module, a distribution module can be written. + The distribution module is a module with well-defined callbacks, + much like a (there is no compiler support + for checking the callbacks, though). This module implements:

+ + + The details of finding other nodes (that is, talking to + epmd or something similar) + Creating a listen port (or similar) + Connecting to other nodes + Performing the handshakes/cookie verification + + +

There is however a utility module, , which + does most of the hard work of handling handshakes, cookies, timers, + and ticking. Using makes implementing a + distribution module much easier and that is done in + the example application.

+
+ +
+ Creating Boot Scripts +

The last step is to create boot scripts to make the protocol + implementation available at boot time. The implementation can be + debugged by starting the distribution when all the system is + running, but in a real system the distribution is to start very + early, why a boot script and some command-line parameters are + necessary.

+ +

This step also implies that the Erlang code in the + interface and distribution modules is written in such a way that + it can be run in the startup phase. In particular, there can be no + calls to the module or to any modules + not loaded at boot time. That is, only , + , and the application itself can be used.

+
- The driver -

Although Erlang drivers in general may be beyond the scope of this - document, a brief introduction seems to be in place.

+ The Driver +

Although Erlang drivers in general can be beyond the scope of this + section, a brief introduction seems to be in place.

- Drivers in general + Drivers in General

An Erlang driver is a native code module written in C (or - assembler) which serves as an interface for some special operating + assembler), which serves as an interface for some special operating system service. This is a general mechanism that is used throughout the Erlang emulator for all kinds of I/O. An Erlang driver can be dynamically linked (or loaded) to the Erlang emulator at runtime by using the Erlang module. Some of the drivers in OTP are however statically linked - to the runtime system, but that's more an optimization than a + to the runtime system, but that is more an optimization than a necessity.

-

The driver data-types and the functions available to the driver - writer are defined in the header file (there - is also an deprecated version called , 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.

+ +

The driver data types and the functions available to the driver + writer are defined in header file (there + is also a deprecated version called , do not + use that one) seated in Erlang's include directory (and in + $ERL_TOP/erts/emulator/beam in the source code + distribution). See that file for function prototypes, and so on.

+

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.

+ about that particular protocol. All operation must be + non-blocking and all possible situations are to be accounted for in + the driver. A non-stable driver will affect and/or crash the + whole Erlang runtime system.

+

The emulator calls the driver in the following situations:

+ - 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 struct, - which should be properly filled in (see below). - When a port to the driver is opened (by a - call from Erlang). This routine should set up internal data - structures and return an opaque data entity of the type - , 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. - 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 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 rather than in a single buffer. There is no - need for a distribution driver to implement such a call-back, so - we wont. - 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 - . The mechanism of driver select makes it - possible to read non blocking from file descriptors by calling - when reading is needed and then do the actual - reading in this call-back (when reading is actually possible). The - typical scenario is that 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. - 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 - . 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. - When a port is closed, either by an Erlang process or by the - driver calling one of the routines. This - routine should clean up everything connected to one particular - port. Note that when other call-backs call a - 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 not be called until the - queue is empty. - When an Erlang process calls erlang:port_control/3, - 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. - When a timer expires. The driver can set timers with the - function . When such timers expire, a - specific call-back function is called. We will not use timers in - our example. - When the whole driver is unloaded. Every resource allocated - by the driver should be freed. + +

When the driver is loaded. This callback must have a special + name and inform the emulator of what callbacks are to be used + by returning a pointer to a struct, + which is to be properly filled in (see below).

+
+ +

When a port to the driver is opened (by a + call from Erlang). This routine is to + set up internal data structures and return an opaque data entity of + the type , which is a data type large + enough to hold a pointer. + The pointer returned by this function is the first + argument to all other callbacks concerning this particular + port. It is usually called the port handle. The emulator only + stores the handle and does never try to interpret it, why it can + be virtually anything (anything not larger than a pointer + that is) and can point to anything if it is a pointer. Usually + this pointer refers to a structure holding information about + the particular port, as it does in the example.

+
+ +

When an Erlang process sends data to the port. The data + arrives as a buffer of bytes, the interpretation is not defined, + but is up to the implementor. This callback returns nothing to the + caller, answers are sent to the caller as messages (using a + routine called available to all + drivers). There is also a way to talk in a synchronous way to + drivers, described below. There can be an additional callback + function for handling data that is fragmented (sent in a deep + io-list). That interface gets the data in a form suitable for + Unix rather than in a single buffer. + There is no need for a distribution driver to implement such a + callback, so we will not.

+
+ +

When a file descriptor is signaled for input. This callback + is called when the emulator detects input on a file descriptor + that the driver has marked for monitoring by using the interface + . The mechanism of driver select + makes it possible to read non-blocking from file descriptors by + calling when reading is needed, and + then do the reading in this callback (when reading is possible). + The typical scenario is that 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.

+
+ +

When a file descriptor is signaled for output. This callback + is called in a similar way as the previous, but when writing to a + file descriptor is possible. The usual scenario is that Erlang + orders writing on a file descriptor and that the driver calls + . When the descriptor is ready for + output, this callback is called and the driver can try to send the + output. Queuing can be involved in such operations, and there are + convenient queue routines available to the driver writer to use.

+
+ +

When a port is closed, either by an Erlang process or by the + driver calling one of the + routines. This routine is to clean up everything connected to one + particular port. When other callbacks call a + routine, this routine is + immediately called. The callback routine issuing the error can + make no more use of the data structures for the port, as this + routine surely has freed all associated data and closed all file + descriptors. If the queue utility available to driver writer is + used, this routine is however not called until the + queue is empty.

+
+ +

When an Erlang process calls + + erlang:port_control/3, + which is a synchronous interface to drivers. The control interface + is used to set driver options, change states of ports, and so on. + This interface is used a lot in the example.

+
+ +

When a timer expires. The driver can set timers with the function + . When such timers expire, a + specific callback function is called. No timers are used in + the example.

+
+ +

When the whole driver is unloaded. Every resource allocated + by the driver is to be freed.

+
- The distribution driver's data structures -

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 + The Data Structures of the Distribution Driver +

The driver used for Erlang distribution is to implement a + reliable, order maintaining, variable length packet-oriented + protocol. All error correction, resending and such need to be implemented in the driver or by the underlying communications - protocol. If the protocol is stream oriented (as is the case with + protocol. If the protocol is stream-oriented (as is the case with both TCP/IP and our streamed Unix domain sockets), some mechanism for packaging is needed. We will use the simple method of having a - header of four bytes containing the length of the package in a big - endian 32 bit integer (as Unix domain sockets only can be used - between processes on the same machine, we actually don't need to - code the integer in some special endianess, but I'll do it anyway - because in most situation you do need to do it. Unix domain - sockets are reliable and order maintaining, so we don't need to - implement resends and such in our driver.

-

Lets start writing our example Unix domain sockets driver by - declaring prototypes and filling in a static ErlDrvEntry - structure.

+ header of four bytes containing the length of the package in a + big-endian 32-bit integer. As Unix domain sockets only can be used + between processes on the same machine, we do not need to + code the integer in some special endianess, but we will do it anyway + because in most situation you need to do it. Unix domain + sockets are reliable and order maintaining, so we do not need to + implement resends and such in the driver.

+ +

We start writing the example Unix domain sockets driver by + declaring prototypes and filling in a static ErlDrvEntry + structure:

+ ( 2) #include @@ -286,94 +355,123 @@ (51) NULL, /* process_exit callback */ (52) NULL /* stop_select callback */ (53) };]]> -

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 exists, why we can define the preprocessor - variable before we include - at line 12. The definition of will make the + +

On line 1-10 the OS headers needed for the driver are included. + As this driver is written for Solaris, we know that the + header exists. So the preprocessor variable + can be defined before + is included on line 12. + The definition of will make the I/O vectors used in Erlang's driver queues to correspond to the operating systems ditto, which is very convenient.

-

The different call-back functions are declared ("forward - declarations") on line 16 to 23.

-

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 + +

On line 16-23 the different callback functions are declared ("forward + declarations").

+ +

The driver structure is similar for statically linked-in + drivers and dynamically loaded. However, some of the fields + are to be left empty (that is, initialized to NULL) in the different types of drivers. The first field (the 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 outputv field + driver, see line 26. NULL on line 37 + is always to be there, the field is no longer used and is + retained for backward compatibility. No timers are used in this + driver, why no callback for timers is needed. The outputv field (line 40) can be used to implement an interface similar to Unix for output. The Erlang runtime - system could previously not use outputv 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 outputv callback. Using the outputv - callback is preferred since it reduces copying of data. (We - will however use scatter/gather I/O internally in the driver).

-

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 - ERL_DRV_FLAG_SOFT_BUSY - 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 output and outputv 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 - set_busy_port()). -

+ system could previously not use outputv for the + distribution, but it can as from ERTS 5.7.2. + As this driver was written before ERTS 5.7.2 it does + not use the outputv callback. Using the outputv + callback is preferred, as it reduces copying of data. (We + will however use scatter/gather I/O internally in the driver.)

+ +

As from ERTS 5.5.3 the driver interface was extended with + version control and the possibility to pass capability information. + Capability flags are present on line 48. As from ERTS 5.7.4 flag + + ERL_DRV_FLAG_SOFT_BUSY is required for drivers that + are to be used by the distribution. The soft busy flag implies that the + driver can handle calls to the output and outputv + callbacks although it has marked itself as busy. This has always been a + requirement on drivers used by the distribution, but no capability + information has been available about this previously. For more + information. see + erl_driver:set_busy_port()).

+

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 - ERL_DRV_FLAG_USE_PORT_LOCKING - as a driver flag. This is left as an exercise for the reader.

-

Our defined call-backs thus are:

- - uds_start, which shall initiate data for a port. We wont - create any actual sockets here, just initialize data structures. - uds_stop, the function called when a port is closed. - 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. - uds_input, this is the call-back which is called when we have - something to read from a socket. - uds_output, this is the function called when we can write to a - socket. - 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. - uds_control, the erlang:port_control/2 call-back, which - will be used a lot in this implementation. - -

The ports implemented by this driver will operate in two major - modes, which i will call the command and data - 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.

-

While the 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 - intermediate mode.

-

Lets define an enum for the different types of ports we have:

+ 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 + ERL_DRV_FLAG_USE_PORT_LOCKING as a driver flag. This + is left as an exercise for the reader.

+ +

Thus, the defined callbacks are as follows:

+ + + uds_start + +

Must initiate data for a port. We do not create any sockets + here, only initialize data structures.

+
+ uds_stop + +

Called when a port is closed.

+
+ uds_command + +

Handles messages from Erlang. The + messages can either be plain data to be sent or more subtle + instructions to the driver. This function is here mostly for + data pumping.

+
+ uds_input + +

Called when there is something to read from a socket.

+
+ uds_output + +

Called when it is possible to write to a socket.

+
+ uds_finish + +

Called when the driver is unloaded. A distribution driver will + actually (or hopefully) never be unloaded, but we include this for + completeness. To be able to clean up after oneself is always a good + thing.

+
+ uds_control + +

The + erlang:port_control/3 callback, which is + used a lot in this implementation.

+
+
+ +

The ports implemented by this driver operate in two major modes, + named command and data. In command mode, + only passive reading and writing (like + gen_tcp:recv/gen_tcp:send) can be done. The port is in + this mode during the distribution handshake. When the connection is up, + the port is switched to data mode and all data is immediately + read and passed further to the Erlang emulator. In data + mode, no data arriving to uds_command is interpreted, only + packaged and sent out on the socket. The uds_control callback + does the switching between those two modes.

+ +

While informs different subsystems + that the connection is coming up, the port is to accept data to send. + However, the port receives no data, to avoid that data arrives from + another node before every kernel subsystem is prepared to handle it. + A third mode, named intermediate, is used for this + intermediate stage.

+ +

An enum is defined for the different types of ports:

+ -

Lets look at the different types:

- - portTypeUnknown - The type a port has when it's opened, but - not actually bound to any file descriptor. - 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. - 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. - 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. - portTypeCommand - A connected socket (or accepted socket if - you want) that is in the command mode mentioned earlier. - portTypeIntermediate - The intermediate stage for a connected - socket. There should be no processing of input for this socket. - 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 socket. - -

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.

+ +

The different types are as follows:

+ + + portTypeUnknown + +

The type a port has when it is opened, but + not bound to any file descriptor.

+
+ portTypeListener + +

A port that is connected to a listen socket. This port does not + do much, no data pumping is done on this socket, but read data is + available when one is trying to do an accept on the port.

+
+ portTypeAcceptor + +

This port is to represent the result of an accept operation. It is + created when one wants to accept from a listen socket, and it is + converted to a portTypeCommand when the accept succeeds.

+
+ portTypeConnector + +

Very similar to portTypeAcceptor, an + intermediate stage between the request for a connect operation and + that the socket is connected to an accepting ditto in the + other end. When the sockets are connected, the port + switches type to portTypeCommand.

+
+ portTypeCommand + +

A connected socket (or accepted socket) in command mode + mentioned earlier.

+
+ portTypeIntermediate + +

The intermediate stage for a connected socket. + There is to be no processing of input for this socket.

+
+ portTypeData + +

The mode where data is pumped through the port and the + uds_command routine regards every call as a call where + sending is wanted. In this mode, all input available is read and + sent to Erlang when it arrives on the socket, much like in the + active mode of a socket.

+
+
+ +

We study the state that is needed for the ports. Notice + that not all fields are used for all types of ports. Some space + could be saved by using unions, but that would clutter the + code with multiple indirections, so here is used one struct for + all types of ports, for readability:

+ +

This structure is used for all types of ports although some fields are useless for some types. The least memory consuming solution would be to arrange this structure as a union of - structures, but the multiple indirections in the code to - access a field in such a structure will clutter the code to + structures. However, the multiple indirections in the code to + access a field in such a structure would clutter the code too much for an example.

-

Let's look at the fields in our structure:

- - fd - The file descriptor of the socket associated with the - port. - port - The port identifier for the port which this structure - corresponds to. It is needed for most - calls from the driver back to the emulator. + +

The fields in the structure are as follows:

+ + + fd -

lockfd - If the socket is a listen socket, we use a separate +

The file descriptor of the socket associated with the port.

+
+ port + +

The port identifier for the port that this structure + corresponds to. It is needed for most + calls from the driver back to the emulator.

+
+ lockfd + +

If the socket is a listen socket, we use a separate (regular) file for two purposes:

- 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. -

We store the creation serial number in the - file. The creation is a number that should +

We want a locking mechanism that gives no race + conditions, to be sure if another Erlang + node uses the listen socket name we require or if the + file is only left there from a previous (crashed) session.

+
+ +

We store the creation serial number in the + file. The creation is a number that is to change between different instances of different Erlang emulators with the same name, so that process - identifiers from one emulator won't be valid when sent + identifiers from one emulator do not become valid when sent to a new emulator with the same distribution name. The - creation can be between 0 and 3 (two bits) and is stored - in every process identifier sent to another node.

-

In a system with TCP based distribution, this data is + creation can be from 0 through 3 (two bits) and is stored + in every process identifier sent to another node.

+

In a system with TCP-based distribution, this data is kept in the Erlang port mapper daemon (), which is contacted when a distributed - node starts. The lock-file and a convention for the UDS - listen socket's name will remove the need for + node starts. The lock file and a convention for the UDS + listen socket's name remove the need for when using this distribution module. UDS is always restricted to one host, why avoiding a port mapper is easy.

- 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. - type - The current type/state of the port, which can be one - of the values declared above. - name - The name of the socket file (the path prefix - removed), which allows for deletion () when the - socket is closed. - 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 ticker uses this value by calling the - driver to fetch it, which is done through the - erlang:port_control routine). - received - How many bytes that are read (received) from the - socket, used in similar ways as . - 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. - 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. - 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. -
+ 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 + finds our value in the file.

+
+ type + +

The current type/state of the port, which can be one + of the values declared above.

+
+ name + +

The name of the socket file (the path prefix removed), + which allows for deletion () when the + socket is closed.

+
+ sent + +

How many bytes that have been sent over the + socket. This can wrap, but that is no problem for the + distribution, as the Erlang distribution is only interested in + if this value has changed. (The Erlang + net_kernel ticker uses this value by calling the + driver to fetch it, which is done through the + + erlang:port_control/3 routine.)

+
+ received + +

How many bytes that are read (received) from the + socket, used in similar ways as .

+
+ partner + +

A pointer to another port structure, which is + either the listen port from which this port is accepting a + connection or conversely. The "partner relation" + is always bidirectional.

+
+ 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.

+
+ buffer_size, buffer_pos, header_pos, + buffer + +

Data for input buffering. For details about the input buffering, + see the source code in directory kernel/examples. That + certainly goes beyond the scope of this section.

+
+
- Selected parts of the distribution driver implementation -

The distribution drivers implementation is not completely - covered in this text, details about buffering and other things + Selected Parts of the Distribution Driver Implementation +

The implemenation of the distribution driver is not completely + covered here, details about buffering and other things unrelated to driver writing are not explained. Likewise are some peculiarities of the UDS protocol not explained in detail. The chosen protocol is not important.

-

Prototypes for the driver call-back routines can be found in + +

Prototypes for the driver callback routines can be found in the header file.

+

The driver initialization routine is (usually) declared with a macro to make the driver easier to port between different - operating systems (and flavours of systems). This is the only - routine that has to have a well defined name. All other - call-backs are reached through the driver structure. The macro + operating systems (and flavors of systems). This is the only + routine that must have a well-defined name. All other + callbacks are reached through the driver structure. The macro to use is named and takes the driver name - as parameter.

+ as parameter:

+ +

The routine initializes the single global data structure and - returns a pointer to the driver entry. The routine will be - called when is called from Erlang.

-

The routine is called when a port is opened - from Erlang. In our case, we only allocate a structure and + returns a pointer to the driver entry. The routine is called + when is called from Erlang.

+ +

The routine is called when a port is + opened from Erlang. In this case, we only allocate a structure and initialize it. Creating the actual socket is left to the routine.

+ -

Every data item is initialized, so that no problems will arise + +

Every data item is initialized, so that no problems arise when a newly created port is closed (without there being any corresponding socket). This routine is called when - is called from Erlang.

-

The routine is the routine called when an - Erlang process sends data to the port. All asynchronous - commands when the port is in command mode as well as - the sending of all data when the port is in data mode - is handled in this9s routine. Let's have a look at it:

+ is called from + Erlang.

+ +

The routine is the routine called when + an Erlang process sends data to the port. This routine handles all + asynchronous commands when the port is in command mode and + the sending of all data when the port is in data mode:

+ -

The command routine takes three parameters; the handle - returned for the port by , which is a pointer - to the internal port structure, the data buffer and the length + +

The command routine takes three parameters; the handle returned for + the port by , 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).

-

If Erlang sends i.e. the list to the port, - the variable will be ant the - variable will contain (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:

- - 'L'<socketname>: Create and listen on socket with the - given name. - '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. - 'C'<socketname>: Connect to the socket named - <socketname>. - '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. - 'R': Receive one packet of data. - -

One may wonder what is meant by "one packet of data" in the - 'R' command. This driver always sends data packeted with a 4 - byte header containing a big endian 32 bit integer that + (a list of bytes) converted to an C array (of bytes).

+ +

If Erlang sends, for example, the list + to the port, the variable is + and the variable contains + (no + NULL termination). Usually the first byte is used as an + opcode, which is the case in this driver too (at least when the + port is in command mode). The opcodes are defined as follows:

+ + + 'L'<socket name> + +

Creates and listens on socket with the specified name.

+
+ 'A'<listen number as 32-bit big-endian> + +

Accepts from the listen socket identified by the specified + identification number. The identification number is retrieved with + the uds_control routine.

+
+ 'C'<socket name> + +

Connects to the socket named <socket name>.

+
+ 'S'<data> + +

Sends the data <data> on the + connected/accepted socket (in command mode). The sending is + acknowledged when the data has left this process.

+
+ 'R' + +

Receives one packet of data.

+
+
+ +

"One packet of data" in command 'R' can be explained + as follows. This driver always sends data packaged with a 4 + byte header containing a big-endian 32-bit integer that represents the length of the data in the packet. There is no need for different packet sizes or some kind of streamed - mode, as this driver is for the distribution only. One may - wonder why the header word is coded explicitly in big endian - when an UDS socket is local to the host. The answer simply is - that I see it as a good practice when writing a distribution - driver, as distribution in practice usually cross the host - boundaries.

-

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 routine to report - errors. One important thing to remember is that the failure - routines make a call to our routine, which - will remove the internal port data. The handle (and the casted - handle ) is therefore invalid pointers after a - call and we should immediately return. The runtime system will send exit signals to all + mode, as this driver is for the distribution only. + Why is the header word coded explicitly in big-endian when a UDS + socket is local to the host? It is good practice when writing a + distribution driver, as distribution in practice usually crosses + the host boundaries.

+ +

On line 4-8 is handled the case where the port is in data mode + or intermediate mode and the remaining routine handles the + different commands. The routine uses the + routine to report errors + (see, for example, line 15). Notice that the failure routines make + a call to the routine, which will + remove the internal port data. The handle (and the casted handle + ) is therefore invalid pointers after a + call and we should return + immediately. The runtime system will send exit signals to all linked processes.

-

The uds_input routine gets called when data is available on a - file descriptor previously passed to the - routine. Typically this happens when a read command is issued - and no data is available. Lets look at the - routine:

+ +

The uds_input routine is called when data is available on a + file descriptor previously passed to the + routine. This occurs typically when + a read command is issued and no data is available. The + routine is as follows:

+ +

The routine tries to read data until a packet is read or the routine returns a - (an internally defined constant for - the module that means that the read operation resulted in an - ). 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 call-back be called when - more data is available for reading.

-

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 + (an internally defined constant + for the module, which means that the read operation resulted in an + ). If the port is in command mode, + the reading stops when one package is read. If the port 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 (which + is always the case when the socket is in data mode), + driver_select is called to make the + callback be called when more data is available for reading.

+ +

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 - is defined to. The tagging of data - in the distribution will possibly change in the future.

-

The routine will handle other input events - (like nonblocking ), but most importantly handle + the current emulator version, received data is to be tagged + with a single byte of 100. That is what the macro + is defined to. The tagging of + data in the distribution can be changed in the future.

+ +

The routine handles other input events + (like non-blocking ), but most importantly + handle data arriving at the socket by calling :

+ -

The important line here is the last line in the function, the - 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 + +

The important line is the last line in the function: the + routine is called to handle new input. + The remaining function handles input on a listen socket, which means + that it is to be possible to do an accept on the socket, which is also recognized as a read event.

-

The output mechanisms are similar to the input. Lets first - look at the routine:

+ +

The output mechanisms are similar to the input. + The routine is as follows:

+ port, &eio, written); (38) send_out_queue(ud); (39) } ]]> +

This driver uses the system call to send data - onto the socket. A combination of writev and the driver output - queues is very convenient. An ErlIOVec structure - contains a SysIOVec (which is equivalent to the - structure defined in . The - ErlIOVec also contains an array of ErlDrvBinary + onto the socket. A combination of writev and the driver output + queues is very convenient. An ErlIOVec structure + contains a SysIOVec (which is equivalent to the + structure defined in + . The + ErlIOVec also contains an array of ErlDrvBinary pointers, of the same length as the number of buffers in the I/O vector itself. One can use this to allocate the binaries - for the queue "manually" in the driver, but we'll just fill - the binary array with NULL values (line 7) , which will make - the runtime system allocate its own buffers when we call - (line 37).

-

+ for the queue "manually" in the driver, but here + the binary array is filled with NULL values (line 7). + The runtime system then allocates its own buffers when + is called (line 37).

+

The routine builds an I/O vector containing the header bytes and the buffer (the opcode has been removed and the buffer length decreased by the output routine). If the queue is - empty, we'll write the data directly to the socket (or at + empty, we write the data directly to the socket (or at least try to). If any data is left, it is stored in the queue - and then we try to send the queue (line 38). An ack is sent - when the message is delivered completely (line 22). The - will send acks if the sending is - completed there. If the port is in command mode, the Erlang + and then we try to send the queue (line 38). An acknowledgement + is sent when the message is delivered completely (line 22). The + sends acknowledgements 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.

-

-

A short look at the routine:

+ can be waiting for delivery at a time. Therefore the acknowledgement + can be sent whenever the queue is empty.

+ +

The routine is as follows:

+ sent += wrote; (29) } (30) } ]]> -

What we do is simply to pick out an I/O vector from the queue - (which is the whole queue as an SysIOVec). If the I/O - vector is to long (IO_VECTOR_MAX is defined to 16), the vector + +

We simply pick out an I/O vector from the queue + (which is the whole queue as a SysIOVec). If the I/O + vector is too long (IO_VECTOR_MAX is defined to 16), the vector length is decreased (line 15), otherwise the - (line 17) call will - fail. Writing is tried and anything written is dequeued (line - 27). If the write fails with (note that all - sockets are in nonblocking mode), is + call (line 17) fails. Writing is tried and anything written is dequeued + (line 27). + If the write fails with (notice that all + sockets are in non-blocking mode), is called to make the routine be called when there is space to write again.

-

We will continue trying to write until the queue is empty or - the writing would block.

-

The routine above are called from the - routine, which looks like this:

+ +

We continue trying to write until the queue is empty or + the writing blocks.

+ +

The routine above is called from the + routine:

+ -

The routine is simple, it first handles the fact that the + +

The routine is simple: it first handles the fact that the output select will concern a socket in the business of connecting (and the connecting blocked). If the socket is in - a connected state it simply sends the output queue, this - routine is called when there is possible to write to a socket + a connected state, it simply sends the output queue. This + routine is called when it is possible to write to a socket where we have an output queue, so there is no question what to do.

+

The driver implements a control interface, which is a synchronous interface called when Erlang calls - . This is the only interface - that can control the driver when it is in data mode and it may + + erlang:port_control/3. Only this interface + can control the driver when it is in data mode. It can be called with the following opcodes:

- - 'C': Set port in command mode. - 'I': Set port in intermediate mode. - 'D': Set port in data mode. - '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. - '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. - '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. - Note that it is important that the interface for - sending ticks is not blocking. This implementation uses - erlang:port_control/3 which does not block the caller. - If erlang:port_command is used, use - erlang:port_command/3 and pass [force] 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. - '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. - + + + 'C' + +

Sets port in command mode.

+
+ 'I' + +

Sets port in intermediate mode.

+
+ 'D' + +

Sets port in data mode.

+
+ 'N' + +

Gets identification number for listen port. This + identification number is used in an accept command to the + driver. It is returned as a big-endian 32-bit integer, which + is the file identifier for the listen socket.

+
+ 'S' + +

Gets statistics, which is the number of bytes received, + the number of bytes sent, and the number of bytes pending in + the output queue. This data is used when the distribution + checks that a connection is alive (ticking). The statistics + is returned as three 32-bit big-endian integers.

+
+ 'T' + +

Sends 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.

+

Note: It is important that the interface for + sending ticks is not blocking. This implementation uses + + erlang:port_control/3, which does not block the + caller. If erlang:port_command is used, use + + erlang:port_command/3 and pass [force] 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.

+
+ 'R' + +

Gets creation number of a listen socket, which is used to + dig out the number stored in the lock file to differentiate + between invocations of Erlang nodes with the same name.

+
+
+

The control interface gets a buffer to return its value in, - but is free to allocate its own buffer is the provided one is - to small. Here is the code for :

+ but is free to allocate its own buffer if the provided one is + too small. The code is as follows:

+ -

The macro (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 on - line 45), but turn off read selection in intermediate and - command modes (line 27 and 36).

-

The rest of the driver is more or less UDS specific and not of + +

The macro (line 5-10) is used to ensure that + the buffer is large enough for the answer. We switch on the command and + take actions. We always have read select active on a port in data + mode (achieved by calling on line 45), but + we turn off read selection in intermediate and command + modes (line 27 and 36).

+ +

The rest of the driver is more or less UDS-specific and not of general interest.

- Putting it all together -

To test the distribution, one can use the - function, which is useful as it starts - the distribution on a running system, where tracing/debugging - can be performed. The routine takes a - list as its single argument. The lists first element should be - the node name (without the "@hostname") as an atom, and the second (and - last) element should be one of the atoms or - . In the example case is - preferred.

-

For net kernel to find out which distribution module to use, the - command line argument 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 + Putting It All Together +

To test the distribution, the + function can be used. It is useful, as it starts the distribution on a + running system, where tracing/debugging can be performed. + The routine takes a + list as its single argument. The list first element in the list is to be + the node name (without the "@hostname") as an atom. The second (and + last) element is to be one of the atoms or + . In the example case, + is preferred.

+ +

For net_kernel to find out which distribution module to use, + command-line argument is used. It + is followed by one or more distribution module names, with suffix + "_dist" removed, that is, uds_dist as a distribution module is specified as .

-

If no epmd (TCP port mapper daemon) is used, one should also - specify the command line option , which will make - Erlang skip the epmd startup, both as a OS process and as an + +

If no epmd (TCP port mapper daemon) is used, also command-line + option is to be specified, which makes + Erlang skip the epmd startup, both as an OS process and as an Erlang ditto.

+

The path to the directory where the distribution modules reside - must be known at boot, which can either be achieved by - specifying ]]> 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).

-

The distribution will be started at boot if all the above is + must be known at boot. This can be achieved either by + specifying ]]> on the command line or by + building a boot script containing the applications used for your + distribution protocol. (In the uds_dist protocol, only the + uds_dist application needs to be added to the script.)

+ +

The distribution starts at boot if all the above is specified and an ]]> flag is present at the - command line, here follows two examples:

+ command line.

+ +

Example 1:

+
 $ erl -pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin -proto_dist uds -no_epmd
 Erlang (BEAM) emulator version 5.0 
@@ -1074,7 +1310,9 @@ Eshell V5.0  (abort with ^G)
 1> net_kernel:start([bing,shortnames]).
 {ok,<0.30.0>}
 (bing@hador)2>
-

...

+ +

Example 2:

+
 $ erl -pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin -proto_dist uds \ 
       -no_epmd -sname bong
@@ -1082,8 +1320,10 @@ Erlang (BEAM) emulator version 5.0
  
 Eshell V5.0  (abort with ^G)
 (bong@hador)1>
-

One can utilize the ERL_FLAGS environment variable to store the + +

The ERL_FLAGS environment variable can be used to store the complicated parameters in:

+
 $ ERL_FLAGS=-pa $ERL_TOP/lib/kernel/examples/uds_dist/ebin \ 
       -proto_dist uds -no_epmd
@@ -1093,8 +1333,8 @@ Erlang (BEAM) emulator version 5.0
  
 Eshell V5.0  (abort with ^G)
 (bang@hador)1>
-

The should preferably not include the name of - the node.

+ +

should not include the node name.

diff --git a/erts/doc/src/communication.xml b/erts/doc/src/communication.xml index 1eb05310e9..632ca6c212 100644 --- a/erts/doc/src/communication.xml +++ b/erts/doc/src/communication.xml @@ -26,63 +26,72 @@ Rickard Green - + uy 2012-12-03 PA1 communication.xml

Communication in Erlang is conceptually performed using - asynchronous signaling. All different executing entities - such as processes, and ports communicate via asynchronous + asynchronous signaling. All different executing entities, + such as processes and ports, communicate through asynchronous signals. The most commonly used signal is a message. Other - common signals are exit, link, unlink, monitor, demonitor + common signals are exit, link, unlink, monitor, and demonitor signals.

+
Passing of Signals -

The amount of time that passes between a signal being sent +

The amount of time that passes between a signal is sent and the arrival of the signal at the destination is unspecified - but positive. If the receiver has terminated, the signal will - not arrive, but it is possible that it triggers another signal. - For example, a link signal sent to a non-existing process will - trigger an exit signal which will be sent back to where the link + but positive. If the receiver has terminated, the signal does + not arrive, but it can trigger another signal. + For example, a link signal sent to a non-existing process + triggers an exit signal, which is sent back to where the link signal originated from. When communicating over the distribution, - signals may be lost if the distribution channel goes down.

-

The only signal ordering guarantee given is the following. If + signals can be lost if the distribution channel goes down.

+ +

The only signal ordering guarantee given is the following: if an entity sends multiple signals to the same destination entity, - the order will be preserved. That is, if A sends + the order is preserved; that is, if A sends a signal S1 to B, and later sends - the signal S2 to B, S1 is guaranteed not to + signal S2 to B, S1 is guaranteed not to arrive after S2.

+
Synchronous Communication

Some communication is synchronous. If broken down into pieces, - a synchronous communication operation, consists of two asynchronous - signals. One request signal and one reply signal. An example of - such a synchronous communication is a call to process_info/2 - when the first argument is not self(). The caller will send - an asynchronous signal requesting information, and will then - wait for the reply signal containing the requested information. When - the request signal reaches its destination the destination process + a synchronous communication operation consists of two asynchronous + signals; one request signal and one reply signal. An example of + such a synchronous communication is a call to + + erlang:process_info/2 + when the first argument is not self(). The caller sends + an asynchronous signal requesting information, and then + waits for the reply signal containing the requested information. When + the request signal reaches its destination, the destination process replies with the requested information.

+
Implementation -

The implementation of different asynchronous signals in the - VM may vary over time, but the behaviour will always respect this +

The implementation of different asynchronous signals in the virtual + machine can vary over time, but the behavior always respects this concept of asynchronous signals being passed between entities as described above.

-

By inspecting the implementation you might notice that some - specific signal actually gives a stricter guarantee than described + +

By inspecting the implementation, you might notice that some + specific signal gives a stricter guarantee than described above. It is of vital importance that such knowledge about the - implementation is not used by Erlang code, since the - implementation might change at any time without prior notice.

-

Some example of major implementation changes:

+ implementation is not used by Erlang code, as the + implementation can change at any time without prior notice.

+ +

Examples of major implementation changes:

+ - As of ERTS version 5.5.2 exit signals to processes are truly + As from ERTS 5.5.2 exit signals to processes are truly asynchronously delivered. - As of ERTS version 5.10 all signals from processes to ports + As from ERTS 5.10 all signals from processes to ports are truly asynchronously delivered.
diff --git a/erts/doc/src/crash_dump.xml b/erts/doc/src/crash_dump.xml index 0b827ae583..f143be87d6 100644 --- a/erts/doc/src/crash_dump.xml +++ b/erts/doc/src/crash_dump.xml @@ -22,7 +22,7 @@ - How to interpret the Erlang crash dumps + How to Interpret the Erlang Crash Dumps Patrik Nyblom @@ -32,401 +32,539 @@ PA1 crash_dump.xml -

This document describes the file generated - upon abnormal exit of the Erlang runtime system.

-

Important: 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.

-

The system will write the crash dump in the current directory of +

This section describes the file + generated upon abnormal exit of the Erlang runtime system.

+ + +

The Erlang crash dump had a major facelift in Erlang/OTP R9C. The + information + in this section is therefore not directly applicable for older dumps. + However, if you use the + crashdump_viewer tool in the Observer application + on older dumps, + the crash dumps are translated into a format similar to this.

+
+ +

The system writes the crash dump in the current directory of the emulator or in the file pointed out by the environment variable (whatever that means on the current operating system) - ERL_CRASH_DUMP. For a crash dump to be written, there has to be a - writable file system mounted.

+ ERL_CRASH_DUMP. For a crash dump to be written, a + writable file system must be mounted.

+

Crash dumps are written mainly for one of two reasons: either the - builtin function is called explicitly with a - string argument from running Erlang code, or else the runtime + built-in function is called explicitly + with a string argument from running Erlang code, or the runtime system has detected an error that cannot be handled. The most - usual reason that the system can't handle the error is that the + usual reason that the system cannot handle the error is that the cause is external limitations, such as running out of memory. A - crash dump due to an internal error may be caused by the system + crash dump caused by an internal error can be caused by the system reaching limits in the emulator itself (like the number of atoms - in the system, or too many simultaneous ets tables). Usually the + in the system, or too many simultaneous ets tables). Usually the emulator or the operating system can be reconfigured to avoid the crash, which is why interpreting the crash dump correctly is important.

+

On systems that support OS signals, it is also possible to stop - the runtime system and generate a crash dump by sending the SIGUSR1.

-

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 - application will simplify the task. This is an - wx-widget based tool for browsing Erlang crash dumps.

+ the runtime system and generate a crash dump by sending the SIGUSR1 + signal.

+ +

The Erlang crash dump is a readable text file, but it can be difficult + to read. Using the Crashdump Viewer tool in the + application simplifies the task. This is a + wx-widget-based tool for browsing Erlang crash dumps.

- General information -

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, the number of - atoms in the atom table and the runtime system thread that caused - the crash dump to happen. -

+ General Information +

The first part of the crash dump shows the following:

+ + + 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 + The number of atoms in the atom table + The runtime system thread that caused the crash dump +
- Reasons for crash dumps (slogan) -

The reason for the dump is noted in the beginning of the file - as Slogan: <reason> (the word "slogan" has historical - roots). If the system is halted by the BIF + Reasons for Crash Dumps (Slogan) +

The reason for the dump is shown in the beginning of the file as:

+ +
+Slogan: <reason>
+ +

(The word "slogan" has historical roots.) + If the system is halted by the BIF , 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 only suggestions. The exact reasons for the errors may vary + is enough to understand the problem, but + some messages are described here. Notice that the + suggested reasons for the crash are only suggestions. + The exact reasons for the errors can vary depending on the local applications and the underlying operating system.

- - "<A>: Cannot allocate <N> - bytes of memory (of type "<T>")." - 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 , , - , or . For more information on - allocators see - erts_alloc(3). - "<A>: Cannot reallocate <N> - bytes of memory (of type "<T>")." - Same as - above with the exception that memory was being reallocated - instead of being allocated when the system ran out of memory. - "Unexpected op code N" - Error in compiled - code, file damaged or error in the compiler. - "Module Name undefined" "Function - Name undefined" "No function - Name:Name/1" "No function - Name:start/2" - The kernel/stdlib applications are - damaged or the start script is damaged. - "Driver_select called with too large file descriptor - " - 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 call). The number of - open regular files is not affected by this. - "Received SIGUSR1" - Sending the SIGUSR1 signal to a - Erlang machine (Unix only) forces a crash dump. This slogan reflects - that the Erlang machine crash-dumped due to receiving that signal. - "Kernel pid terminated (Who) - (Exit-reason)" - The kernel supervisor has detected - a failure, usually that the - has shut down ( = , - = ). 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. - "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 parameter or with a boot script from - the wrong version of OTP. - "Could not start kernel pid (Who) ()" - One of the - kernel processes could not start. This is probably due to - faulty arguments (like errors in a 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. - -

Other errors than the ones mentioned above may occur, as the - BIF may generate any message. If the + + + <A>: Cannot allocate <N> bytes of memory (of type + "<T>") + +

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 , + , , or + . For more information on allocators, see + erts_alloc(3).

+ + <A>: Cannot reallocate <N> bytes of memory (of + type "<T>") + +

Same as above except that memory was reallocated + instead of allocated when the system ran out of memory.

+
+ Unexpected op code <N> + +

Error in compiled code, file damaged, or + error in the compiler.

+
+ Module <Name> undefined Function + <Name> undefined No function + <Name>:<Name>/1 No function + <Name>:start/2 + +

The Kernel/STDLIB applications are + damaged or the start script is damaged.

+
+ Driver_select called with too large file descriptor + + +

The number of file descriptors for sockets + exceeds 1024 (Unix only). The limit on file descriptors in + some Unix flavors can be set to over 1024, but only 1024 + sockets/pipes can be used simultaneously by Erlang (because of + limitations in the Unix call). The number + of open regular files is not affected by this.

+
+ Received SIGUSR1 + +

Sending the SIGUSR1 signal to an Erlang machine (Unix only) + forces a crash dump. This slogan reflects that the Erlang machine + crash-dumped because of receiving that signal.

+
+ Kernel pid terminated (<Who>) (<Exit + reason>) + +

The kernel supervisor has detected a failure, usually that the + has shut down + ( = , + = ). + The application controller + can have shut down for many reasons, the most usual + is that the node name of the distributed Erlang node is + already in use. A complete supervisor tree "crash" (that is, + the top supervisors have exited) gives about the same + result. This message comes from the Erlang code and not from + the virtual machine itself. It is always because of some + failure in an application, either within OTP or a + "user-written" one. Looking at the error log for your + application is probably the first step to take.

+
+ 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 can have been started + with a faulty parameter or with a boot + script from the wrong OTP version.

+
+ Could not start kernel pid (<Who>) () + +

One of the kernel processes could not start. This is probably + because of faulty arguments (like errors in a + argument) + or faulty configuration files. Check that all files are in + their correct location and that the configuration files (if + any) are not damaged. Usually messages are also + written to the controlling terminal and/or the error log + explaining what is wrong.

+
+ + +

Other errors than these can occur, as the + BIF can generate any message. If the message is not generated by the BIF and does not occur in the - list above, it may be due to an error in the emulator. There - may however be unusual messages that I haven't mentioned, that - still are connected to an application failure. There is a lot - more information available, so more thorough reading of the - crash dump may reveal the crash reason. The size of processes, - the number of ets tables and the Erlang data on each process - stack can be useful for tracking down the problem.

+ list above, it can be because of an error in the emulator. There + can however be unusual messages, not mentioned here, which + are still connected to an application failure. There is much + more information available, so a thorough reading of the + crash dump can reveal the crash reason. The size of processes, + the number of ets tables, and the Erlang data on each process + stack can be useful to find the problem.

- Number of atoms + Number of Atoms

The number of atoms in the system at the time of the crash is shown as Atoms: <number>. Some ten thousands atoms is - perfectly normal, but more could indicate that the BIF - is used to dynamically generate a - lot of different atoms, which is never a good idea.

+ perfectly normal, but more can indicate that the BIF + is used to generate many + different atoms dynamically, which is never a good idea.

- Scheduler information -

Under the tag =scheduler information about the current state - and statistics of the schedulers in the runtime system is displayed. - On OSs that do allow instant suspension of other threads, the data within - this section will reflect what the runtime system looks like at the moment - when the crash happens.

+ Scheduler Information +

Under the tag =scheduler is shown information about the current + state and statistics of the schedulers in the runtime system. On + operating systems that allow instant suspension of other threads, the + data within this section reflects what the runtime system looks like + when a crash occurs.

+

The following fields can exist for a process:

+ =scheduler:id - Header, states the scheduler identifier. + +

Heading. States the scheduler identifier.

+
Scheduler Sleep Info Flags - If empty the scheduler was doing some work. - If not empty the scheduler is either in some state of sleep, - or suspended. This entry is only present in a SMP enabled emulator + +

If empty, the scheduler was doing some work. + If not empty, the scheduler is either in some state of sleep, + or suspended. This entry is only present in an SMP-enabled + emulator.

+
Scheduler Sleep Info Aux Work - If not empty, a scheduler internal auxiliary work is scheduled - to be done. + +

If not empty, a scheduler internal auxiliary work is scheduled + to be done.

+
Current Port - The port identifier of the port that is currently being - executed by the scheduler. + +

The port identifier of the port that is currently + executed by the scheduler.

+
Current Process - The process identifier of the process that is currently being - executed by the scheduler. If there is such a process this entry is - followed by the State,Internal State, - Program Counter, CP of that same process. See - Process Information for a - description what the different entries mean. Keep in mind that - this is a snapshot of what the entries are exactly when the crash - dump is starting to be generated. Therefore they will most likely - be different (and more telling) then the entries for the same - processes found in the =proc section. If there is no currently - running process, only the Current Process entry will be printed. + +

The process identifier of the process that is currently + executed by the scheduler. If there is such a process, this entry is + followed by the State, Internal State, + Program Counter, and CP of that same process. + The entries are described in section + Process Information.

+

Notice that this is a snapshot of what the entries are exactly when + the crash dump is starting to be generated. Therefore they are most + likely different (and more telling) than the entries for the same + processes found in the =proc section. If there is no + currently running process, only the Current Process entry is + shown.

Current Process Limited Stack Trace - This entry only shows up if there is a current process. It is very - similar to =proc_stack, - except that only the function frames are printed (i.e. the stack variables - are omited). It is also limited to only print the top and bottom part - of the stack. If the stack is small (less that 512 slots) then the - entire stack will be printed. If not, an entry stating - skipping ## slots will be printed where ## is - replaced by the number of slots that has been skipped. + +

This entry is shown only if there is a current process. It is + similar to + =proc_stack, except that only the function frames + are shown (that is, the stack variables are omitted). + Also, only the top and bottom part of the stack are shown. If the + stack is small (< 512 slots), the entire stack is shown. Otherwise + the entry skipping ## slots is shown, where ## + is replaced by the number of slots that has been skipped.

+
Run Queue - Displays statistics about how many processes and ports - of different priorities are scheduled on this scheduler. + +

Shows statistics about how many processes and ports + of different priorities are scheduled on this scheduler.

+
** crashed ** - This entry is normally not printed. It signifies that getting - the rest of the information about this scheduler failed for some reason. + +

This entry is normally not shown. It signifies that getting the rest + of the information about this scheduler failed for some reason.

- Memory information -

Under the tag =memory you will find information similar - to what you can obtain on a living node with - erlang:memory().

+ Memory Information +

Under the tag =memory is shown information similar + to what can be obtainted on a living node with + + erlang:memory().

- Internal table information -

The tags =hash_table:<table_name> and - =index_table:<table_name> presents internal - tables. These are mostly of interest for runtime system - developers.

+ Internal Table Information +

Under the tags =hash_table:<table_name> and + =index_table:<table_name> is shown internal + tables. These are mostly of interest for runtime system developers.

- Allocated areas -

Under the tag =allocated_areas you will find information - similar to what you can obtain on a living node with - erlang:system_info(allocated_areas).

+ Allocated Areas +

Under the tag =allocated_areas is shown information + similar to what can be obtained on a living node with + + erlang:system_info(allocated_areas).

Allocator -

Under the tag =allocator:<A> you will find +

Under the tag =allocator:<A> is shown various information about allocator <A>. The information - is similar to what you can obtain on a living node with - erlang:system_info({allocator, <A>}). - For more information see the documentation of - erlang:system_info({allocator, <A>}), - and the - erts_alloc(3) - documentation.

+ is similar to what can be obtained on a living node with + + erlang:system_info({allocator, <A>}). + For more information, see also + erts_alloc(3).

- Process information + Process Information

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): -

-

The following fields can exist for a process:

+ process in the system. The following fields can exist for a process:

+ =proc:<pid> - Heading, states the process identifier + +

Heading. States the process identifier.

+
State

The state of the process. This can be one of the following:

- - Scheduled - The process was scheduled to run - but not currently running ("in the run queue"). - Waiting - The process was waiting for - something (in ). - Running - The process was currently - running. If the BIF was called, this was - the process calling it. - Exiting - The process was on its way to - exit. - Garbing - 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. - Suspended - The process is suspended, either - by the BIF or because it is - trying to write to a busy port. - + + Scheduled + The process was scheduled to run + but is currently not running ("in the run queue"). + Waiting + The process was waiting for + something (in ). + Running + The process was currently running. + If the BIF was called, this was + the process calling it. + Exiting + The process was on its way to exit. + Garbing + 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. + Suspended + The process is suspended, either + by the BIF or because + it tries to write to a busy port. +
Registered name - The registered name of the process, if any. + +

The registered name of the process, if any.

+
Spawned as - The entry point of the process, i.e., what function was - referenced in the or call that - started the process. + +

The entry point of the process, that is, what function was + referenced in the or + call that + started the process.

+
Last scheduled in for | Current call - The current function of the process. These fields will not - always exist. + +

The current function of the process. These fields do not + always exist.

+
Spawned by - The parent of the process, i.e. the process which executed - or . + +

The parent of the process, that is, the process that executed + or .

+
Started - The date and time when the process was started. + +

The date and time when the process was started.

+
Message queue length - The number of messages in the process' message queue. + +

The number of messages in the process' message queue.

+
Number of heap fragments - The number of allocated heap fragments. + +

The number of allocated heap fragments.

+
Heap fragment data - 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. + +

Size of fragmented heap data. This is data either created by + messages sent to the process or by the Erlang BIFs. This + amount depends on so many things that this field is utterly + uninteresting.

+
Link list - 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. + +

Process IDs of processes linked to this one. Can also contain + ports. If process monitoring is used, this field also tells in + which direction the monitoring is in effect. That is, a link + "to" a process tells you that the "current" process was + monitoring the other, and a link "from" a process tells you + that the other process was monitoring the current one.

+
Reductions - The number of reductions consumed by the process. + +

The number of reductions consumed by the process.

+
Stack+heap - The size of the stack and heap (they share memory segment) + +

The size of the stack and heap (they share memory segment).

+
OldHeap - 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. + +

The size of the "old heap". The Erlang virtual machine uses + generational garbage collection with two generations. There is + one heap for new data items and one for the data that has + survived two garbage collections. The assumption (which is + almost always correct) is that data surviving two garbage + collections can be "tenured" to a heap more seldom garbage + collected, as they will live for a long period. This is a + usual technique in virtual machines. The sum of the + heaps and stack together constitute most of the + allocated memory of the process.

+
Heap unused, OldHeap unused - The amount of unused memory on each heap. This information is - usually useless. + +

The amount of unused memory on each heap. This information is + usually useless.

+
Stack - If the system uses shared heap, the fields - Stack+heap, OldHeap, Heap unused - and OldHeap unused do not exist. Instead this field - presents the size of the process' stack. + +

If the system uses shared heap, the fields + Stack+heap, OldHeap, Heap unused, + and OldHeap unused do not exist. Instead this field + shows the size of the process stack.

+
Memory - The total memory used by this process. This includes call stack, - heap and internal structures. Same as erlang:process_info(Pid,memory). + +

The total memory used by this process. This includes call stack, + heap, and internal structures. Same as + + erlang:process_info(Pid,memory).

Program counter - 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. + +

The current instruction pointer. This is only of interest for + runtime system developers. The function into which the program + counter points is the current function of the process.

+
CP - 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. + +

The continuation pointer, that is, the return address for the + current call. Usually useless for other than runtime system + developers. This can be followed by the function into which + the CP points, which is the function calling the current + function.

+
Arity - 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. - Internal State - A more detailed internal represantation of the state of - this process. + +

The number of live argument registers. The argument registers + if any are live will follow. These can contain the arguments + of the function if they are not yet moved to the stack.

+
+ Internal State + +

A more detailed internal representation of the state of + this process.

+
-

See also the section about process data.

+

See also section Process Data.

- Port information + Port Information

This section lists the open ports, their owners, any linked - processed, and the name of their driver or external process.

+ processes, and the name of their driver or external process.

- ETS tables -

This section contains information about all the ETS tables in - the system. The following fields are interesting for each table:

+ ETS Tables +

This section contains information about all the ets tables in + the system. The following fields are of interest for each table:

+ =ets:<owner> - Heading, states the owner of the table (a process identifier) + +

Heading. States the table owner (a process identifier).

+
Table - The identifier for the table. If the table is a - , this is the name. + +

The identifier for the table. If the table is a + , this is the name.

+
Name - The name of the table, regardless of whether it is a - or not. + +

The table name, regardless of if it is a + or not.

+
Hash table, Buckets - This occurs if the table is a hash table, i.e. if it is not an - . + +

If the table is a hash table, that is, if it is not an + .

+
Hash table, Chain Length - Only applicable for hash tables. Contains statistics about the - hash table, such as the max, min and avg chain length. Having a max much - larger than the avg, and a std dev much larger that - the expected std dev is a sign that the hashing of the terms is - behaving badly for some reason. + +

If the table is a hash table. Contains statistics about the + table, such as the maximum, minimum, and average chain length. + Having a maximum much larger than the average, and a standard + deviation much larger than the expected standard deviation is + a sign that the hashing of the terms + behaves badly for some reason.

+
Ordered set (AVL tree), Elements - This occurs only if the table is an . (The - number of elements is the same as the number of objects in the - table.) + +

If the table is an . (The + number of elements is the same as the number of objects in the + table.)

+
Fixed - If the table is fixed using ets:safe_fixtable or some internal - mechanism. + +

If the table is fixed using + + ets:safe_fixtable or some internal mechanism.

+
Objects - The number of objects in the table + +

The number of objects in the table.

+
Words - The number of words (usually 4 bytes/word) allocated to data - in the table. + +

The number of words (usually 4 bytes/word) allocated to data + in the table.

+
Type - The type of the table, i.e. set, bag, - dublicate_bag or ordered_set. + +

The table type, that is, set, bag, + dublicate_bag, or ordered_set.

+
Compressed - If this table was compressed. + +

If the table was compressed.

+
Protection - The protection of this table. + +

The protection of the table.

+
Write Concurrency - If write_concurrency was enabled for this table. + +

If write_concurrency was enabled for the table.

+
Read Concurrency - If read_concurrency was enabled for this table. + +

If read_concurrency was enabled for the table.

+
@@ -435,167 +573,252 @@ Timers

This section contains information about all the timers started with the BIFs and - . The following fields exists for each - timer:

+ . The following fields exist + for each timer:

+ =timer:<owner> - Heading, states the owner of the timer (a process identifier) - i.e. the process to receive the message when the timer - expires. + +

Heading. States the timer owner (a process identifier), + that is, the process to receive the message when the timer + expires.

+
Message - The message to be sent. + +

The message to be sent.

+
Time left - Number of milliseconds left until the message would have been - sent. + +

Number of milliseconds left until the message would have been + sent.

+
- Distribution information -

If the Erlang node was alive, i.e., set up for communicating + Distribution Information +

If the Erlang node was alive, that is, set up for communicating with other nodes, this section lists the connections that were active. The following fields can exist:

+ =node:<node_name> - The name of the node + +

The node name.

+
no_distribution - This will only occur if the node was not distributed. + +

If the node was not distributed.

+
=visible_node:<channel> - 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. + +

Heading for a visible node, that is, an alive node with a + connection to the node that crashed. States the channel number + for the node.

+
=hidden_node:<channel> - 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. + +

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.

+
=not_connected:<channel> - 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. + +

Heading for a node that was connected to the crashed + node earlier. References (that is, process or port identifiers) + to the not connected node existed at the time of the crash. + States the channel number for the node.

+
Name - The name of the remote node. + +

The name of the remote node.

+
Controller - The port which controls the communication with the remote node. + +

The port controlling communication with the remote node.

+
Creation - An integer (1-3) which together with the node name identifies - a specific instance of the node. - Remote monitoring: <local_proc> <remote_proc> - The local process was monitoring the remote process at the - time of the crash. - Remotely monitored by: <local_proc> <remote_proc> - The remote process was monitoring the local process at the - time of the crash. + +

An integer (1-3) that together with the node name identifies + a specific instance of the node.

+
+ Remote monitoring: <local_proc> <remote_proc> + + +

The local process was monitoring the remote process at the + time of the crash.

+
+ Remotely monitored by: <local_proc> + <remote_proc> + +

The remote process was monitoring the local process at the + time of the crash.

+
Remote link: <local_proc> <remote_proc> - A link existed between the local process and the remote - process at the time of the crash. + +

A link existed between the local process and the remote + process at the time of the crash.

+
- Loaded module information -

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.

-

All loaded modules are then listed. The following fields exist:

+ Loaded Module Information +

This section contains information about all loaded modules.

+ +

First, the memory use by the loaded code is summarized:

+ + + Current code + +

Code that is the current latest version of the modules.

+
+ Old code + +

Code where there exists a newer version in the + system, but the old version is not yet purged.

+
+
+ +

The memory use is in bytes.

+ +

Then, all loaded modules are listed. The following fields exist:

+ =mod:<module_name> - Heading, and the name of the module. + +

Heading. States the module name.

+
Current size - Memory usage for the loaded code in bytes + +

Memory use for the loaded code, in bytes.

+
Old size - Memory usage for the old code, if any. + +

Memory use for the old code, if any.

+
Current attributes - Module attributes for the current code. This field is decoded - when looked at by the Crashdump Viewer tool. + +

Module attributes for the current code. This field is decoded + when looked at by the Crashdump Viewer tool.

+
Old attributes - Module attributes for the old code, if any. This field is - decoded when looked at by the Crashdump Viewer tool. + +

Module attributes for the old code, if any. This field is + decoded when looked at by the Crashdump Viewer tool.

+
Current compilation info - Compilation information (options) for the current code. This - field is decoded when looked at by the Crashdump Viewer tool. + +

Compilation information (options) for the current code. This + field is decoded when looked at by the Crashdump Viewer tool.

+
Old compilation info - Compilation information (options) for the old code, if - any. This field is decoded when looked at by the Crashdump - Viewer tool. + +

Compilation information (options) for the old code, if + any. This field is decoded when looked at by the Crashdump + Viewer tool.

+
- Fun information -

In this section, all funs are listed. The following fields exist - for each fun:

+ Fun Information +

This section lists all funs. The following fields exist for each fun:

+ =fun - Heading + +

Heading.

+
Module - The name of the module where the fun was defined. + +

The name of the module where the fun was defined.

+
Uniq, Index - Identifiers + +

Identifiers.

+
Address - The address of the fun's code. + +

The address of the fun's code.

+
Native_address - The address of the fun's code when HiPE is enabled. + +

The address of the fun's code when HiPE is enabled.

+
Refc - The number of references to the fun. + +

The number of references to the fun.

+
Process Data -

For each process there will be at least one =proc_stack - and one =proc_heap tag followed by the raw memory +

For each process there is at least one =proc_stack + and one =proc_heap tag, followed by the raw memory information for the stack and heap of the process.

-

For each process there will also be a =proc_messages - tag if the process' message queue is non-empty and a - =proc_dictionary tag if the process' dictionary (the - and thing) is non-empty.

+ +

For each process there is also a =proc_messages + tag if the process message queue is non-empty, and a + =proc_dictionary tag if the process dictionary (the + and thing) is + non-empty.

+

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).

+ Viewer tool. You can then see the stack dump, the + message queue (if any), and the dictionary (if any).

+

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 in the example below:

+ the live data (that is, variables currently in use) are placed on + the stack; thus this can be interesting. One has to + "guess" what is what, but as the information is symbolic, + thorough reading of this information can be useful. As an + example, we can find the state variable of the Erlang primitive + loader online and + in the following example:

+ ) -(2) y(0) ["/view/siri_r10_dev/clearcase/otp/erts/lib/kernel/ebin","/view/siri_r10_dev/ -(3) clearcase/otp/erts/lib/stdlib/ebin"] +(2) y(0) ["/view/siri_r10_dev/clearcase/otp/erts/lib/kernel/ebin", +(3) "/view/siri_r10_dev/clearcase/otp/erts/lib/stdlib/ebin"] (4) y(1) <0.1.0> -(5) y(2) {state,[],none,#Fun,undefined,#Fun,#Fun,#Port<0.2>,infinity,#Fun} -(6) y(3) infinity ]]> +(5) y(2) {state,[],none,#Fun,undefined,#Fun, +(6) #Fun,#Port<0.2>,infinity,#Fun} +(7) y(3) infinity ]]> +

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.

+ that anonymous function objects (funs) are given the following:

+ + + A name constructed from the name of the function in which they are + created + + A number (starting with 0) indicating the number of that fun within + that function + +
Atoms -

Now all the atoms in the system are written. This is only - interesting if one suspects that dynamic generation of atoms could +

This section presents all the atoms in the system. This is only + of interest if one suspects that dynamic generation of atoms can be a problem, otherwise this section can be ignored.

-

Note that the last created atom is printed first.

+ +

Notice that the last created atom is shown first.

Disclaimer -

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 +

The format of the crash dump evolves between OTP releases. + Some information described here may not apply to your + version. A description like this will never be complete; it is meant as an explanation of the crash dump in general and as a help when trying to find application errors, not as a complete specification.

diff --git a/erts/doc/src/driver.xml b/erts/doc/src/driver.xml index 4bef5e1388..2dae01b143 100644 --- a/erts/doc/src/driver.xml +++ b/erts/doc/src/driver.xml @@ -22,103 +22,115 @@ - How to implement a driver + How to Implement a Driver Jakob C 2000-11-28 PA1 driver.xml - -

This document was written a long time ago. A lot of it is still - interesting since it explains important concepts, but it was - written for an older driver interface so the examples do not - work anymore. The reader is encouraged to read - erl_driver and the - driver_entry documentation. -

+ +

This section was written a long time ago. Most of it is still + valid, as it explains important concepts, but this was + written for an older driver interface so the examples do not + work anymore. The reader is encouraged to read the + erl_driver and + driver_entry + documentation also.

+
Introduction -

This chapter tells you how to build your own driver for erlang.

-

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.

+

This section describes how to build your own driver for Erlang.

+ +

A driver in Erlang is a library written in C, which is linked to + the Erlang emulator and called from Erlang. Drivers can be used + when C is more suitable than Erlang, to speed up things, or to + provide access to OS resources not directly accessible from Erlang.

+

A driver can be dynamically loaded, as a shared library (known as - a DLL on windows), or statically loaded, linked with the emulator + a DLL on Windows), or statically loaded, linked with the emulator when it is compiled and linked. Only dynamically loaded drivers are described here, statically linked drivers are beyond the scope - of this chapter.

-

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!

-

+ of this section.

+ + +

When a driver is loaded it is executed in the context of the + emulator, shares the same memory and the same thread. This means + that all operations in the driver must be non-blocking, and that + any crash in the driver brings the whole emulator down. In short, + be careful.

+
- Sample driver -

This is a simple driver for accessing a postgres + Sample Driver +

This section describes a simple driver for accessing a postgres database using the libpq C client library. Postgres - is used because it's free and open source. For information - on postgres, refer to the website - www.postgres.org.

+ is used because it is free and open source. For information on postgres, + see www.postgres.org.

+

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.

-

The code is quite straight-forward: all + the client library. This is only for simplicity, but not good, as it + halts the emulator while waiting for the database. + This is improved below with an asynchronous sample driver.

+ +

The code is straightforward: all communication between Erlang and the driver is done with , and the driver returns data back using the .

+

An Erlang driver only exports one function: the driver entry function. This is defined with a macro, - , and returns a pointer to a + , which returns a pointer to a C containing the entry points that are called from the emulator. The defines the entries that the emulator calls to call the driver, with a pointer for entries that are not defined and used by the driver.

+

The entry is called when the driver is opened as a port with . Here we allocate memory for a user data structure. - This user data will be passed every time the emulator - calls us. First we store the driver handle, because it - is needed in subsequent calls. We allocate memory for + This user data is passed every time the emulator + calls us. First we store the driver handle, as it + is needed in later calls. We allocate memory for the connection handle that is used by LibPQ. We also set the port to return allocated driver binaries, by - setting the flag , calling + setting flag , calling . (This is because - we don't know whether our data will fit in the - result buffer of , which has a default size - set up by the emulator, currently 64 bytes.)

-

There is an entry which is called when - the driver is loaded, but we don't use this, since + we do not know if our data will fit in the + result buffer of , which has a default size, + 64 bytes, set up by the emulator.)

+ +

An entry is called when + the driver is loaded. However, we do not use this, as it is executed only once, and we want to have the possibility of several instances of the driver.

+

The entry is called when the port is closed.

+

The entry is called from the emulator when the Erlang code calls , to do the actual work. We have defined a simple set of - commands: to login to the database, - to log out and to send a SQL-query and get the result. + commands: to log on to the database, + to log out, and + to send a SQL-query and get the result. All results are returned through . - The library in is used - to encode data in binary term format. The result is returned + The library in is + used to encode data in binary term format. The result is returned to the emulator as binary terms, so is called in Erlang to convert the result to term form.

-

The code is available in in the - directory of .

+ +

The code is available in in the + directory of .

+

The driver entry contains the functions that - will be called by the emulator. In our simple - example, we only provide , - and .

+ will be called by the emulator. In this simple example, + only , , + and are provided:

+ +

We have a structure to store state needed by the driver, - in this case we only need to keep the database connection.

+ in this case we only need to keep the database connection:

+ -

These are control codes we have defined.

+ +

The control codes that we have defined are as follows:

+ -

This just returns the driver structure. The macro + +

This only returns the driver structure. The macro defines the only exported function. All the other functions are static, and will not be exported from the library.

+ -

Here we do some initialization, is called from - . The data will be passed to - and .

+ +

Here some initialization is done, is called from + . The data will be passed to + and .

+ +

We call disconnect to log out from the database. (This should have been done from Erlang, but just in case.)

+ +

We use the binary format only to return data to the emulator; - input data is a string paramater for and + input data is a string parameter for and . The returned data consists of Erlang terms.

-

The functions and are - utilities that are used to make the code shorter. - duplicates the string and zero-terminates it, since the + +

The functions and + are utilities that are used to + make the code shorter. + duplicates the string and zero-terminates it, as the postgres client library wants that. - takes an buffer and allocates a binary and - copies the data there. This binary is returned in . - (Note that this binary is freed by the emulator, not by us.)

+ takes an buffer, allocates a binary, and + copies the data there. This binary is returned in + . + (Notice that this binary is freed by the emulator, not by us.)

+ -

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 in the driver data.

+ +

is where we log on to the database. If the + connection was successful, we store the connection handle in the driver + data, and return OK. Otherwise, we return the error message + from postgres and store in the driver data.

+ -

If we are connected (if the connection handle is not ), + +

If we are connected (and if the connection handle is not + ), we log out from the database. We need to check if we should - encode an ok, since we might get here from the - function, which doesn't return data to the emulator.

+ encode an OK, as we can get here from function , + which does not return data to the emulator:

+ -

We execute a query and encode the result. Encoding is done - in another C module, which is also provided + +

We execute a query and encode the result. Encoding is done in + another C module, , which is also provided as sample code.

+ -

Here we simply check the result from postgres, and - if it's data we encode it as lists of lists with + +

Here we check the result from postgres. + If it is data, we encode it as lists of lists with column data. Everything from postgres is C strings, - so we just use to send + so we only use to send the result as strings to Erlang. (The head of the list contains the column names.)

+
- Compiling and linking the sample driver -

The driver should be compiled and linked to a shared - library (DLL on windows). With gcc this is done - with the link flags and . - Since we use the library we should include + Compiling and Linking the Sample Driver +

The driver is to be compiled and linked to a shared + library (DLL on Windows). With gcc, this is done with + link flags and . + As we use the library, we should include it too. There are several versions of , compiled for debug or non-debug and multi-threaded or single-threaded. - In the makefile for the samples the directory + In the makefile for the samples, the directory is used for the library, meaning that we use the non-debug, single-threaded version.

- Calling a driver as a port in Erlang + Calling a Driver as a Port in Erlang

Before a driver can be called from Erlang, it must be loaded and opened. Loading is done using the module (the driver that loads dynamic - driver, is actually a driver itself). If loading is ok + driver is actually a driver itself). If loading is OK, the port can be opened with . The port name must match the name of the shared library and the name in the driver entry structure.

+

When the port has been opened, the driver can be called. In - the example, we don't have any data from + the example, we do not have any data from the port, only the return value from the .

+

The following code is the Erlang part of the synchronous - postgres driver, .

+ postgres driver, :

+ select(Port, Query) -> binary_to_term(port_control(Port, ?DRV_SELECT, Query)). ]]> -

The API is simple: loads the driver, opens it - and logs on to the database, returning the Erlang port - if successful, sends a query to the driver, - and returns the result, closes the - database connection and the driver. (It does not unload it, - however.) The connection string should be a connection - string for postgres.

-

The driver is loaded with , - and if this is successful, or if it's already loaded, + +

The API is simple:

+ + + +

loads the driver, opens it, + and logs on to the database, returning the Erlang port + if successful.

+
+ +

sends a query to the driver + and returns the result.

+
+ +

closes the database + connection and the driver. (However, it does not unload it.)

+
+
+ +

The connection string is to be a connection string for postgres.

+ +

The driver is loaded with . + If this is successful, or if it is already loaded, it is opened. This will call the function in the driver.

+

We use the function for all - calls into the driver, the result from the driver is - returned immediately, and converted to terms by calling + calls into the driver. The result from the driver is + returned immediately and converted to terms by calling . (We trust that the terms returned from the driver are well-formed, otherwise the calls could be contained in a @@ -415,16 +469,18 @@ select(Port, Query) ->

- Sample asynchronous driver -

Sometimes database queries can take long time to + Sample Asynchronous Driver +

Sometimes database queries can take a long time to complete, in our driver, the emulator halts while the driver is doing its job. This is - often not acceptable, since no other Erlang process + often not acceptable, as no other Erlang process gets a chance to do anything. To improve on our - postgres driver, we reimplement it using the asynchronous + postgres driver, we re-implement it using the asynchronous calls in LibPQ.

-

The asynchronous version of the driver is in the - sample files and .

+ +

The asynchronous version of the driver is in the sample files + and .

+ -

Here some things have changed from : we use the - entry for and - which will be called from the emulator only - when there is input to be read from the socket. (Actually, the + +

Some things have changed from : we use + the entry for + and , which is called from the emulator + only when there is input to be read from the socket. (Actually, the socket is used in a function inside - the emulator, and when the socket is signalled, - indicating there is data to read, the entry - is called. More on this below.)

+ the emulator, and when the socket is signaled, + indicating there is data to read, the + entry is called. More about this below.)

+

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 - . We have a flag to tell + . We have a flag + to tell whether the driver is waiting for a connection or waiting - for the result of a query. (This is needed since the entry - will be called both when connecting and + for the result of a query. (This is needed, as the entry + is called both when connecting and when there is a query result.)

+ -

The function looks a bit different too. We connect - using the asynchronous function. After the - connection is started, we retrieve the socket for the connection + +

The function looks a bit different too. We + connect using the asynchronous function. + After the connection is started, we retrieve the socket for the connection with . This socket is used with the function to wait for connection. When - the socket is ready for input or for output, the - function will be called.

-

Note that we only return data (with ) if there + the socket is ready for input or for output, the + function is called.

+ +

Notice that we only return data (with ) + if there is an error here, otherwise we wait for the connection to be completed, - in which case our function will be called.

+ in which case our function is called.

+ +

The function initiates a select, and returns - if there is no immediate error. The actual result will be returned + if there is no immediate error. The result is returned when is called.

+ -

The function will be called when the socket + +

The function is called when the socket we got from postgres is ready for input or output. Here we first check if we are connecting to the database. In that - case we check connection status and return ok if the - connection is successful, or error if it's not. If the - connection is not yet established, we simply return; - will be called again.

+ case, we check connection status and return OK if the + connection is successful, or error if it is not. If the + connection is not yet established, we simply return; + is called again.

+

If we have a result from a connect, indicated by having data in the buffer, we no longer need to select on output (), so we remove this by calling .

-

If we're not connecting, we're waiting for results from a + +

If we are not connecting, we wait for results from a , so we get the result and return it. The encoding is done with the same functions as in the earlier example.

-

We should add error handling here, for instance checking - that the socket is still open, but this is just a simple - example.

+ +

Error handling is to be added here, for example, checking + that the socket is still open, but this is only a simple example.

+

The Erlang part of the asynchronous driver consists of the sample file .

+ binary_to_term(Data) end. ]]> -

The Erlang code is slightly different, this is because we - don't return the result synchronously from , + +

The Erlang code is slightly different, as we do not + return the result synchronously from , instead we get it from as data in the message queue. The function above - receives data from the port. Since the data is in + receives data from the port. As the data is in binary format, we use to convert - it to an Erlang term. Note that the driver is opened in - binary mode ( is called with the option + it to an Erlang term. Notice that the driver is opened in + binary mode ( is called with option ). This means that data sent from the driver - to the emulator is sent as binaries. Without the - option, they would have been lists of integers.

+ to the emulator is sent as binaries. Without option + , they would have been lists of integers.

- An asynchronous driver using driver_async -

As a final example we demonstrate the use of . + An Asynchronous Driver Using driver_async +

As a final example we demonstrate the use of + . 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 algorithm to get the next permutation - of a list of integers. For large lists (more than 100000 - elements), this will take some time, so we will perform this + in C++. This enables us to use an algorithm from STL. We use + the algorithm to get the next + permutation of a list of integers. For large lists (> 100,000 + elements), this takes some time, so we perform this as an asynchronous task.

-

The asynchronous API for drivers is quite complicated. First - of all, the work must be prepared. In our example we do this - in . We could have used just as well, - but we want some variation in our examples. In our driver, we allocate - a structure that contains anything that's needed for the asynchronous task - to do the work. This is done in the main emulator thread. + +

The asynchronous API for drivers is complicated. First, + the work must be prepared. In the example, this is done in + . We could have used , + but we want some variation in the examples. In our driver, we allocate + a structure that contains anything that is needed for the asynchronous + task to do the work. This is done in the main emulator thread. Then the asynchronous function is called from a driver thread, - separate from the main emulator thread. Note that the driver-functions - are not reentrant, so they shouldn't be used. + separate from the main emulator thread. Notice that the driver functions + are not re-entrant, so they are not to be used. Finally, after the function is completed, the driver callback 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.)

-

The code below is from the sample file .

-

The driver entry looks like before, but also contains the - call-back .

+ this is where we return the result to Erlang. (We cannot + return the result from within the asynchronous function, as + we cannot call the driver functions.)

+ +

The following code is from the sample file + . The driver entry looks like before, + but also contains the callback .

+ -

The 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, + +

The function allocates the work area of the + asynchronous function. As we use C++, we use a struct, + and stuff the data in it. We must copy the original data, it is not valid after we have returned from the - function, and the function will be called later, - and from another thread. We return no data here, instead it will - be sent later from the call-back.

-

The will be passed to the function. - We do not use a function (the last argument to - ), it's only used if the task is cancelled + function, and the function is called + later, and from another thread. We return no data here, instead it + is sent later from the callback.

+ +

The is passed to the + function. We do not use a + function (the last argument to + ), it is only used if the task is cancelled programmatically.

+ -

In the we simply do the work, operating + +

In the we do the work, operating on the structure that was allocated in .

+ data.begin(), d->data.end()); } ]]> -

In the function, the output is sent back to the + +

In the function the output is sent back + to the emulator. We use the driver term format instead of . - This is the only way to send Erlang terms directly to a driver, - without having the Erlang code to call . In - our simple example this works well, and we don't need to use + This is the only way to send Erlang terms directly to a driver, without + having the Erlang code to call . In + the simple example this works well, and we do not need to use to handle the binary term format.

-

When the data is returned we deallocate our data.

+ +

When the data is returned, we deallocate our data.

+ -

This driver is called like the others from Erlang, however, since + +

This driver is called like the others from Erlang. However, as we use , there is no need to call - binary_to_term. The Erlang code is in the sample file + binary_to_term. The Erlang code is in the sample file .

+

The input is changed into a list of integers and sent to the driver.

+ driver_entry.xml driver_entry - The driver-entry structure used by erlang drivers. + The driver-entry structure used by Erlang drivers. -

Use this functionality with extreme care!

+ +

Use this functionality with extreme care.

A driver callback is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can not provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the driver callback function doesn't behave well, - the whole VM will misbehave.

- -

A driver callback that crash will crash the whole VM.

-

An erroneously implemented driver callback might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the driver callback.

-

A driver callback that do - lengthy work - before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.

+ native code of the VM. Execution is not made in a safe environment. + The VM cannot provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the driver callback function does not behave well, + the whole VM will misbehave.

+ + +

A driver callback that crash will crash the whole VM.

+
+ +

An erroneously implemented driver callback can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the driver callback.

+
+ +

A driver callback doing + lengthy work + before returning degrades responsiveness of the VM, and can cause + miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad + load balancing between schedulers. Strange behaviors that can + occur because of lengthy work can also vary between Erlang/OTP + releases.

+
-
-

- As of erts version 5.9 (OTP release R15B) the driver interface + + +

As from ERTS 5.9 (Erlang/OTP R15B) the driver interface has been changed with larger types for the callbacks - output, - control and - call. + output, + control, and + call. See driver version management in - erl_driver. -

+ erl_driver.

+

Old drivers (compiled with an erl_driver.h from an - earlier erts version than 5.9) have to be updated and have - to use the extended interface (with - version management - ).

+ ERTS version earlier than 5.9) must be updated and have + to use the extended interface (with + version management + ).

-

The driver_entry structure is a C struct that all erlang - drivers define. It contains entry points for the erlang driver - that are called by the erlang emulator when erlang code accesses + +

The driver_entry structure is a C struct that all Erlang + drivers define. It contains entry points for the Erlang driver, + which are called by the Erlang emulator when Erlang code accesses the driver.

-

- - The erl_driver driver + +

+ The erl_driver driver API functions need a port handle that identifies the driver instance (and the port in the emulator). This is only passed to the start function, but @@ -90,416 +99,466 @@ common practice is to have the start function allocate some application-defined structure and stash the port handle in it, to use it later with the driver API functions.

-

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 + +

The driver callback functions are called synchronously from the + Erlang emulator. If they take too long before completing, they + can cause time-outs in the emulator. Use the queue or + asynchronous calls if necessary, as the emulator must be responsive.

-

The driver structure contains the name of the driver and some - 15 function pointers. These pointers are called at different + +

The driver structure contains the driver name and some + 15 function pointers, which are called at different times by the emulator.

+

The only exported function from the driver is driver_init. This function returns the driver_entry structure that points to the other functions in the driver. The - driver_init function is declared with a macro - DRIVER_INIT(drivername). (This is because different OS's - have different names for it.)

-

When writing a driver in C++, the driver entry should be of - "C" linkage. One way to do this is to put this line - somewhere before the driver entry: - extern "C" DRIVER_INIT(drivername);.

+ driver_init function is declared with a macro, + DRIVER_INIT(drivername). (This is because different + operating systems have different names for it.)

+ +

When writing a driver in C++, the driver entry is to be of + "C" linkage. One way to do this is to put the + following line somewhere before the driver entry:

+ +
+extern "C" DRIVER_INIT(drivername);
+

When the driver has passed the driver_entry over to the emulator, the driver is not allowed to modify the driver_entry.

-

If compiling a driver for static inclusion via --enable-static-drivers you - have to define STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.

+ +

If compiling a driver for static inclusion through + --enable-static-drivers, you must define + STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.

+ -

Do not declare the driver_entry const. This since the emulator needs to - modify the handle, and the handle2 - fields. A statically allocated, and const - declared driver_entry may be located in - read only memory which will cause the emulator - to crash.

+

Do not declare the driver_entry const. + This because the emulator must + modify the handle and the handle2 + fields. A statically allocated, and const-declared + driver_entry can be located in + read-only memory, which causes the emulator to crash.

- DATA TYPES - - ErlDrvEntry - -

+ Data Types +

ErlDrvEntry

typedef struct erl_drv_entry { - int (*init)(void); /* called at system start up for statically + int (*init)(void); /* Called at system startup for statically linked drivers, and after loading for - dynamically loaded drivers */ - + dynamically loaded drivers */ #ifndef ERL_SYS_DRV ErlDrvData (*start)(ErlDrvPort port, char *command); - /* called when open_port/2 is invoked. - return value -1 means failure. */ + /* Called when open_port/2 is invoked, + return value -1 means failure */ #else ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts); - /* special options, only for system driver */ + /* Special options, only for system driver */ #endif void (*stop)(ErlDrvData drv_data); - /* called when port is closed, and when the - emulator is halted. */ + /* Called when port is closed, and when the + emulator is halted */ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); - /* called when we have output from erlang to + /* Called when we have output from Erlang to the port */ void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when we have input from one of + /* Called when we have input from one of the driver's handles */ void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when output is possible to one of + /* Called when output is possible to one of the driver's handles */ - char *driver_name; /* name supplied as command - in open_port XXX ? */ - void (*finish)(void); /* called before unloading the driver - - DYNAMIC DRIVERS ONLY */ - void *handle; /* Reserved -- Used by emulator internally */ + char *driver_name; /* Name supplied as command in + erlang:open_port/2 */ + void (*finish)(void); /* Called before unloading the driver - + dynamic drivers only */ + void *handle; /* Reserved, used by emulator internally */ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); - /* "ioctl" for drivers - invoked by + /* "ioctl" for drivers - invoked by port_control/3 */ - void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ + void (*timeout)(ErlDrvData drv_data); + /* Handling of time-out in driver */ void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); - /* called when we have output from erlang + /* Called when we have output from Erlang to the port */ void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); void (*flush)(ErlDrvData drv_data); - /* called when the port is about to be - closed, and there is data in the - driver queue that needs to be flushed + /* Called when the port is about to be + closed, and there is data in the + driver queue that must be flushed before 'stop' can be called */ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags); /* Works mostly like 'control', a synchronous - call into the driver. */ + call into the driver */ void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data); - /* Called when an event selected by + /* 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 *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; - -

+ } ErlDrvEntry; - int (*init)(void) - -

This is called directly after the driver has been loaded by - erl_ddll:load_driver/2. (Actually when the driver is - added to the driver list.) The driver should return 0, or if - the driver can't initialize, -1.

+ int (*init)(void) + +

Called directly after the driver has been loaded by + + erl_ddll:load_driver/2 (actually when the driver is + added to the driver list). The driver is to return 0, or, if + the driver cannot initialize, -1.

- ErlDrvData (*start)(ErlDrvPort port, char* command) + + ErlDrvData (*start)(ErlDrvPort port, char* command) -

This is called when the driver is instantiated, when - open_port/2 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:

-

ERL_DRV_ERROR_GENERAL - general error, no error code

-

ERL_DRV_ERROR_ERRNO - error with error code in errno

-

ERL_DRV_ERROR_BADARG - error, badarg

-

If an error code is returned, the port isn't started.

+

Called when the driver is instantiated, when + + erlang:open_port/2 is called. + The driver is to return a number >= 0 or a pointer, or, if the + driver cannot be started, one of three error codes:

+ + ERL_DRV_ERROR_GENERAL + General error, no error code + ERL_DRV_ERROR_ERRNO + Error with error code in errno + ERL_DRV_ERROR_BADARG + Error, badarg + +

If an error code is returned, the port is not started.

- void (*stop)(ErlDrvData drv_data) + void (*stop)(ErlDrvData drv_data) -

This is called when the port is closed, with - port_close/1 or Port ! {self(), close}. Note - that terminating the port owner process also closes the +

Called when the port is closed, with + + erlang:port_close/1 or Port ! {self(), close}. + Notice that terminating the port owner process also closes the port. If drv_data is a pointer to memory allocated in - start, then stop is the place to deallocate that - memory.

+ start, then stop is the place to deallocate that + memory.

- void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) + + void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) + -

This is called when an erlang process has sent data to the - port. The data is pointed to by buf, and is - len bytes. Data is sent to the port with Port ! {self(), {command, Data}}, or with - port_command/2. Depending on how the port was opened, - it should be either a list of integers 0...255 or a - binary. See open_port/3 and port_command/2.

+

Called when an Erlang process has sent data to the port. The data is + pointed to by buf, and is len bytes. Data is sent to + the port with Port ! {self(), {command, Data}} or with + erlang:port_command/2. Depending on how the port was + opened, it is to be either a list of integers 0...255 or a + binary. See + erlang:open_port/2 and + + erlang:port_command/2.

- - void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event) - - void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event) + + void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event) + + + + void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event) + -

This is called when a driver event (given in the - event parameter) is signaled. This is used to help - asynchronous drivers "wake up" when something happens.

-

On unix the event is a pipe or socket handle (or +

Called when a driver event (specified in parameter + event) is signaled. This is used to help + asynchronous drivers "wake up" when something occurs.

+

On Unix the event is a pipe or socket handle (or something that the select system call understands).

-

On Windows the event is an Event or Semaphore (or - something that the WaitForMultipleObjects API +

On Windows the event is an Event or Semaphore + (or something that the WaitForMultipleObjects API function understands). (Some trickery in the emulator allows more than the built-in limit of 64 Events to be used.)

To use this with threads and asynchronous routines, create a - pipe on unix and an Event on Windows. When the routine + pipe on Unix and an Event on Windows. When the routine completes, write to the pipe (use SetEvent on - Windows), this will make the emulator call + Windows), this makes the emulator call ready_input or ready_output.

-

Spurious events may happen. That is, calls to ready_input - or ready_output even though no real events are signaled. In - reality it should be rare (and OS dependant), but a robust driver +

False events can occur. That is, calls to ready_input + or ready_output although no real events are signaled. In + reality, it is rare (and OS-dependant), but a robust driver must nevertheless be able to handle such cases.

- char *driver_name + char *driver_name -

This is the name of the driver, it must correspond to the - atom used in open_port, and the name of the driver +

The driver name. It must correspond to the atom used in + + erlang:open_port/2, and the name of the driver library file (without the extension).

- void (*finish)(void) + void (*finish)(void) -

This function is called by the erl_ddll driver when the +

Called by the erl_ddll driver when the driver is unloaded. (It is only called in dynamic drivers.)

The driver is only unloaded as a result of calling - unload_driver/1, or when the emulator halts.

+ + erl_ddll:unload_driver/1, + or when the emulator halts.

- void *handle + void *handle

This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the driver_entry isn't declared const.

+ emulator will modify this field, so it is important + that the driver_entry is not declared const.

- ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) + + ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) -

This is a special routine invoked with the erlang function - port_control/3. It works a little like an "ioctl" for - erlang drivers. The data given to port_control/3 - arrives in buf and len. The driver may send +

A special routine invoked with + + erlang:port_control/3. + It works a little like an "ioctl" for + Erlang drivers. The data specified to port_control/3 + arrives in buf and len. The driver can send data back, using *rbuf and rlen.

This is the fastest way of calling a driver and get a - response. It won't make any context switch in the erlang - emulator, and requires no message passing. It is suitable - for calling C function to get faster execution, when erlang + response. It makes no context switch in the Erlang + emulator and requires no message passing. It is suitable + for calling C function to get faster execution, when Erlang is too slow.

-

If the driver wants to return data, it should return it in +

If the driver wants to return data, it is to return it in rbuf. When control is called, *rbuf points to a default buffer of rlen bytes, which - can be used to return data. Data is returned different depending on + can be used to return data. Data is returned differently depending on the port control flags (those that are set with - set_port_control_flags). -

+ + erl_driver:set_port_control_flags).

If the flag is set to PORT_CONTROL_FLAG_BINARY, - 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 *rbuf to point to a binary allocated with - driver_alloc_binary. - This binary will be freed automatically after control has returned. + a binary is returned. Small binaries can be returned by writing + the raw data into the default buffer. A binary can also be + returned by setting *rbuf to point to a binary allocated with + + erl_driver:driver_alloc_binary. + This binary is freed automatically after control has returned. The driver can retain the binary for read only access with - driver_binary_inc_refc to be freed later with - driver_free_binary. - It is never allowed to alter the binary after control has returned. - If *rbuf is set to NULL, an empty list will be returned. -

+ + erl_driver:driver_binary_inc_refc to be freed later + with + erl_driver:driver_free_binary. + It is never allowed to change the binary after control has + returned. If *rbuf is set to NULL, an empty list is + returned.

If the flag is set to 0, data is returned as a list of integers. Either use the default buffer or set *rbuf to point to a larger buffer allocated with - driver_alloc. - The buffer will be freed automatically after control has returned.

+ + erl_driver:driver_alloc. The + buffer is freed automatically after control has returned.

Using binaries is faster if more than a few bytes are returned.

-

The return value is the number of bytes returned in - *rbuf.

+

The return value is the number of bytes returned in *rbuf.

- - void (*timeout)(ErlDrvData drv_data) + void (*timeout)(ErlDrvData drv_data) + -

This function is called any time after the driver's timer - reaches 0. The timer is activated with - driver_set_timer. 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.

+

Called any time after the driver's timer reaches 0. + The timer is activated with + + erl_driver:driver_set_timer. No priorities or + ordering exist among drivers, so if several drivers time out at + the same time, anyone of them is called first.

- - void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev) + + void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev) -

This function is called whenever the port is written to. If +

Called whenever the port is written to. If it is NULL, the output function is called - instead. This function is faster than output, because + instead. This function is faster than output, as it takes an ErlIOVec directly, which requires no - copying of the data. The port should be in binary mode, see - open_port/2.

-

The ErlIOVec contains both a SysIOVec, + copying of the data. The port is to be in binary mode, see + + erlang:open_port/2.

+

ErlIOVec contains both a SysIOVec, suitable for writev, and one or more binaries. If - these binaries should be retained, when the driver returns - from outputv, they can be queued (using driver_enq_bin - for instance), or if they are kept in a static or global + these binaries are to be retained when the driver returns + from outputv, they can be queued (using, for example, + + erl_driver:driver_enq_bin) + or, if they are kept in a static or global variable, the reference counter can be incremented.

- void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data) + + void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData + thread_data) -

This function is called after an asynchronous call has - completed. The asynchronous call is started with driver_async. - This function is called from the erlang emulator thread, as +

Called after an asynchronous call has completed. + The asynchronous call is started with + + erl_driver:driver_async. + 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).

+ some thread (if multi-threading is enabled).

+
+ void (*flush)(ErlDrvData drv_data) + +

Called when the port is about to be closed, + and there is data in the driver queue that must be flushed + before 'stop' can be called.

- ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) + ErlDrvSSizeT (*call)(ErlDrvData drv_data, + unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, + ErlDrvSizeT rlen, unsigned int *flags) -

This function is called from erlang:port_call/3. It - works a lot like the control call-back, but uses the +

Called from + erlang:port_call/3. + It works a lot like the control callback, but uses the external term format for input and output.

command is an integer, obtained from the call from - erlang (the second argument to erlang:port_call/3).

+ Erlang (the second argument to erlang:port_call/3).

buf and len provide the arguments to the call (the third argument to erlang:port_call/3). They can be decoded using ei functions.

rbuf points to a return buffer, rlen bytes - long. The return data should be a valid erlang term in the - external (binary) format. This is converted to an erlang + long. The return data is to be a valid Erlang term in the + external (binary) format. This is converted to an Erlang term and returned by erlang:port_call/3 to the - caller. If more space than rlen bytes is needed to + caller. If more space than rlen bytes is needed to return data, *rbuf can be set to memory allocated with - driver_alloc. This memory will be freed automatically - after call has returned.

+ + erl_driver:driver_alloc. + This memory is freed automatically after call has returned.

The return value is the number of bytes returned in *rbuf. If ERL_DRV_ERROR_GENERAL is returned - (or in fact, anything < 0), erlang:port_call/3 will - throw a BAD_ARG.

+ (or in fact, anything < 0), erlang:port_call/3 + throws a BAD_ARG.

- void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data) + void (*event)(ErlDrvData drv_data, ErlDrvEvent event, + ErlDrvEventData event_data)

Intentionally left undocumented.

- int extended_marker + int extended_marker -

- This field should either be equal to ERL_DRV_EXTENDED_MARKER +

This field is either to be equal to ERL_DRV_EXTENDED_MARKER or 0. An old driver (not aware of the extended driver - interface) should set this field to 0. If this field is - equal to 0, all the fields following this field also - have to be 0, or NULL in case it is a - pointer field. -

+ interface) is to set this field to 0. If this field is + 0, all the following fields must also be 0, + or NULL if it is a pointer field.

- int major_version + int major_version -

This field should equal ERL_DRV_EXTENDED_MAJOR_VERSION if - the extended_marker field equals +

This field is to equal ERL_DRV_EXTENDED_MAJOR_VERSION if + field extended_marker equals ERL_DRV_EXTENDED_MARKER.

- int minor_version + int minor_version -

- This field should equal ERL_DRV_EXTENDED_MINOR_VERSION if - the extended_marker field equals - ERL_DRV_EXTENDED_MARKER. -

+

This field is to equal ERL_DRV_EXTENDED_MINOR_VERSION if + field extended_marker equals + ERL_DRV_EXTENDED_MARKER.

- - int driver_flags + int driver_flags

This field is used to pass driver capability and other - information to the runtime system. If the - extended_marker field equals ERL_DRV_EXTENDED_MARKER, - it should contain 0 or driver flags (ERL_DRV_FLAG_*) - ored bitwise. Currently the following driver flags exist: -

+ information to the runtime system. If + field extended_marker equals ERL_DRV_EXTENDED_MARKER, + it is to contain 0 or driver flags (ERL_DRV_FLAG_*) + OR'ed bitwise. The following driver flags exist:

ERL_DRV_FLAG_USE_PORT_LOCKING - 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 - erl_driver - documentation. - +

The runtime system uses port-level locking on + all ports executing this driver instead of driver-level + locking when the driver is run in a runtime + system with SMP support. For more information, see + + erl_driver.

+
ERL_DRV_FLAG_SOFT_BUSY - Marks that driver instances can handle being called - in the output and/or - outputv callbacks even - though a driver instance has marked itself as busy (see - set_busy_port()). - 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). +

Marks that driver instances can handle being called + in the output and/or + outputv callbacks + although a driver instance has marked itself as busy (see + + erl_driver:set_busy_port). + As from ERTS 5.7.4 this flag is required for drivers used + by the Erlang distribution (the behavior has always been + required by drivers used by the distribution).

ERL_DRV_FLAG_NO_BUSY_MSGQ - Disable busy port message queue functionality. For - more information, see the documentation of the - erl_drv_busy_msgq_limits() - function. + +

Disables busy port message queue functionality. For + more information, see + + erl_driver:erl_drv_busy_msgq_limits.

ERL_DRV_FLAG_USE_INIT_ACK - When this flag is given the linked-in driver has to manually - acknowledge that the port has been successfully started using - erl_drv_init_ack(). - This allows the implementor to make the erlang:open_port exit with - badarg after some initial asynchronous initialization has been done. + +

When this flag is specified, the linked-in driver must manually + acknowledge that the port has been successfully started using + + erl_driver:erl_drv_init_ack(). + This allows the implementor to make the + erlang:open_port exit with badarg after some + initial asynchronous initialization has been done.

- void *handle2 + void *handle2 -

- This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the driver_entry isn't declared const. -

+

This field is reserved for the emulator's internal use. The + emulator modifies this field, so it is important + that the driver_entry is not declared const.

- void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor) + + void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor) + -

This callback is called when a monitored process exits. The +

Called when a monitored process exits. The drv_data is the data associated with the port for which - the process is monitored (using driver_monitor_process) - and the monitor corresponds to the ErlDrvMonitor + the process is monitored (using + + erl_driver:driver_monitor_process) + and the monitor corresponds to the ErlDrvMonitor structure filled in when creating the monitor. The driver interface function - driver_get_monitored_process - can be used to retrieve the process id of the exiting process as + + erl_driver:driver_get_monitored_process + can be used to retrieve the process ID of the exiting process as an ErlDrvTermData.

- void (*stop_select)(ErlDrvEvent event, void* reserved) + + void (*stop_select)(ErlDrvEvent event, void* reserved) -

This function is called on behalf of - driver_select - when it is safe to close an event object.

+

Called on behalf of + + erl_driver:driver_select + when it is safe to close an event object.

A typical implementation on Unix is to do - close((int)event).

-

Argument reserved is intended for future use and should be ignored.

-

In contrast to most of the other call-back functions, - stop_select is called independent of any port. No - ErlDrvData argument is passed to the function. No - driver lock or port lock is guaranteed to be held. The port that - called driver_select might even be closed at the - time stop_select is called. But it could also be - the case that stop_select is called directly by - driver_select.

+ close((int)event).

+

Argument reserved is intended for future use and is to be + ignored.

+

In contrast to most of the other callback functions, + stop_select is called independent of any port. No + ErlDrvData argument is passed to the function. No + driver lock or port lock is guaranteed to be held. The port that + called driver_select can even be closed at the + time stop_select is called. But it can also be + the case that stop_select is called directly by + erl_driver:driver_select.

It is not allowed to call any functions in the - driver API from - stop_select. This strict limitation is due to the - volatile context that stop_select may be called.

+ driver API from + stop_select. This strict limitation is because the + volatile context that stop_select can be called.

- - -
-
- SEE ALSO -

erl_driver(3), - erl_ddll(3), - erlang(3), - kernel(3)

+ See Also +

erl_driver(3), + erlang(3), + kernel:erl_ddll(3)

diff --git a/erts/doc/src/epmd.xml b/erts/doc/src/epmd.xml index d9f580d081..7b026e17f8 100644 --- a/erts/doc/src/epmd.xml +++ b/erts/doc/src/epmd.xml @@ -28,242 +28,260 @@ 1 - 98-01-05 + 1998-01-05 A epmd.xml epmd -

Erlang Port Mapper Daemon

- - - -

Starts the port mapper daemon

-
- - -

Communicates with a running port mapper daemon

-
-
+

Erlang Port Mapper Daemon

+ + + + +

Starts the port mapper daemon.

+
+ + +

Communicates with a running port mapper daemon.

+
+
- -

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 + +

This daemon acts as a name server on all hosts involved in + distributed Erlang computations. When an Erlang node starts, + the node has a name and it obtains an address from the host + OS kernel. The name and address are sent to the daemon running on the local host. In a TCP/IP environment, the address consists - of the IP address and a port number. The name of the node is + of the IP address and a port number. The node name is an atom on the form of . The job of the daemon is to keep track of which node name listens on which address. Hence, maps symbolic node names to machine addresses.

-

The TCP/IP epmd daemon actually only keeps track of +

The TCP/IP epmd daemon only keeps track of the Name (first) part of an Erlang node name. The Host part (whatever is after the ) is implicit in the - node name where the epmd daemon was actually contacted, + node name where the epmd daemon was contacted, as is the IP address where the Erlang node can be reached. Consistent and correct TCP naming services are therefore required for an Erlang network to function correctly.

- Starting the port mapper daemon - - -

The daemon is started automatically by the erl - command if the node is to be distributed and there is no - running instance present. If automatically launched, - environment variables have to be used to alter the behavior of - the daemon. See the Environment - variables section below.

- -

If the -daemon argument is not given, - runs as a normal program with the - controlling terminal of the shell in which it is - started. Normally, it should run as a daemon.

- -

Regular start-up options are described in the - Regular options - section below.

- -

The DbgExtra options are described in the - DbgExtra options - section below.

- -
- Communicating with a running port mapper daemon - - -

Communicating with the running epmd daemon by means of the - epmd program is done primarily for debugging - purposes.

- -

The different queries are described in the Interactive options - section below.

- -
-
+ Starting the port mapper daemon + +

The daemon is started automatically by command + erl + if the node is to be distributed and no running + instance is present. If automatically launched + environment variables must be used to change the behavior + of the daemon; see section + Environment + Variables.

+

If argument -daemon is not specified, + runs as a normal program with the + controlling terminal of the shell in which it is + started. Normally, it is to be run as a daemon.

+

Regular startup options are described in section + Regular Options.

+

The DbgExtra options are described in section + DbgExtra Options.

+
+ Communicating with a running port mapper daemon + +

Communicating with the running epmd daemon by the + epmd program is done primarily for debugging purposes.

+

The different queries are described in section Interactive options.

+
+
+
- Regular options + Regular Options +

These options are available when starting the name server. The name + server is normally started automatically by command + erl (if not already available), + but it can also be started at system startup.

-

These options are available when starting the actual name server. The name server is normally started automatically by the erl command (if not already available), but it can also be started at i.e. system start-up.

- - -

Let this instance of epmd listen only on the - comma-separated list of IP addresses and on the loopback address - (which is implicitly added to the list if it has not been - specified). This can also be set using the - environment variable. See the - section Environment - variables below.

-
- - -

Let this instance of epmd listen to another TCP port than - default 4369. This can also be set using the - environment variable. See the - section Environment - variables below

-
- - - -

Enable debug output. The more -d flags given, the more - debug output you will get (to a certain limit). This option is - most useful when the epmd daemon is not started as a daemon.

-
- - -

Start epmd detached from the controlling terminal. Logging will end up in syslog when available and correctly configured. If the epmd daemon is started at boot, this option should definitely be used. It is also used when the erl command automatically starts epmd.

-
- - -

Start the epmd program with relaxed command checking (mostly for backward compatibility). This affects the following:

- - -

With relaxed command checking, the epmd daemon can be killed from the localhost with i.e. epmd -kill even if there are active nodes registered. Normally only daemons with an empty node database can be killed with the epmd -kill command.

+ + +

Lets this instance of epmd listen only on the + comma-separated list of IP addresses and on the loopback address + (which is implicitly added to the list if it has not been + specified). This can also be set using environment variable + ; see section Environment Variables.

+
+ + +

Lets this instance of epmd listen to another TCP port than + default 4369. This can also be set using environment variable + ; see section Environment Variables.

+
+ + +

Enables debug output. The more -d flags specified, the more + debug output you will get (to a certain limit). This option is most + useful when the epmd daemon is not started as a daemon.

+
+ + +

Starts epmd detached from the controlling terminal. Logging + ends up in syslog when available and correctly configured. If the + epmd daemon is started at boot, this option is definitely + to be used. It is also used when command erl automatically + starts epmd.

+
+ + +

Starts the epmd program with relaxed command checking + (mostly for backward compatibility). This affects the following:

+ + +

With relaxed command checking, the epmd daemon can be + killed from the local host with, for example, command + epmd -kill even if active nodes are registered. Normally + only daemons with an empty node database can be killed with + epmd -kill.

-

The epmd -stop command (and the corresponding messages to epmd, as can be given using erl_interface/ei) is normally always ignored, as it opens up the possibility of a strange situation where two nodes of the same name can be alive at the same time. A node unregisters itself by just closing the connection to epmd, which is why the stop command was only intended for use in debugging situations.

-

With relaxed command checking enabled, you can forcibly unregister live nodes.

+

Command epmd -stop (and the corresponding messages to + epmd, as can be specified using erl_interface:ei) is + normally always ignored. This because it can cause a strange + situation where two nodes of the same name can be alive at the + same time. A node unregisters itself by only closing the + connection to epmd, which is why command stop + was only intended for use in debugging situations.

+

With relaxed command checking enabled, you can forcibly + unregister live nodes.

-
-

Relaxed command checking can also be enabled by setting the environment variable ERL_EPMD_RELAXED_COMMAND_CHECK prior to starting epmd.

-

Only use relaxed command checking on systems with very limited interactive usage.

-
-
+ +

Relaxed command checking can also be enabled by setting environment + variable ERL_EPMD_RELAXED_COMMAND_CHECK before starting + epmd.

+

Use relaxed command checking only on systems with very limited + interactive usage.

+ +
- DbgExtra options -

These options are purely for debugging and testing epmd clients. They should not be used in normal operation.

+ DbgExtra Options + +

These options are only for debugging and testing epmd clients. + They are not to be used in normal operation.

+
- - -

Set the number of seconds a connection can be - inactive before epmd times out and closes the - connection (default 60).

-
- - -

To simulate a busy server you can insert a delay between when epmd - gets notified that a new connection is requested and - when the connection gets accepted.

-
- - -

Also a simulation of a busy server. Inserts - a delay before a reply is sent.

-
+ + +

Sets the number of seconds a connection can be + inactive before epmd times out and closes the + connection. Defaults to 60.

+
+ + +

To simulate a busy server, you can insert a delay between when + epmd gets notified that a new connection is requested and + when the connection gets accepted.

+
+ + +

Also a simulation of a busy server. Inserts + a delay before a reply is sent.

+
+
- Interactive options -

These options make epmd run as an interactive command, displaying the results of sending queries to an already running instance of epmd. The epmd contacted is always on the local node, but the -port option can be used to select between instances if several are running using different ports on the host.

- - - -

Contacts the epmd listening on the given TCP port number - (default 4369). This can also be set using the - environment variable. See the - section Environment - variables below.

-
- - -

List names registered with the currently running epmd

-
- - -

Kill the currently running epmd.

+ Interactive Options +

These options make epmd run as an interactive command, + displaying the results of sending queries to an already running + instance of epmd. The epmd contacted is always on the + local node, but option -port can be used to select between + instances if several are running using different ports on the host.

-

Killing the running epmd is only allowed if epmd - -names shows an empty database or - -relaxed_command_check was given when the running - instance of epmd was started. Note that - -relaxed_command_check is given when starting the - daemon that is to accept killing when it has live nodes - registered. When running epmd interactively, - -relaxed_command_check has no effect. A daemon that is - started without relaxed command checking has to be killed - using i.e. signals or some other OS specific method if it has - active clients registered.

-
- - -

Forcibly unregister a live node from epmd's database

- -

This command can only be used when contacting epmd - instances started with the -relaxed_command_check - flag. Note that relaxed command checking has to be enabled for - the epmd daemon contacted. When running epmd - interactively, - -relaxed_command_check has no effect.

-
-
+ + + +

Contacts the epmd listening on the specified TCP port + number (default 4369). This can also be set using environment + variable ; see section Environment Variables.

+
+ + +

Lists names registered with the currently running epmd.

+
+ + +

Kills the currently running epmd.

+

Killing the running epmd is only allowed if + epmd -names shows an empty database or if + -relaxed_command_check was specified when the running + instance of epmd was started.

+

Notice that -relaxed_command_check is specified when + starting the daemon that is to accept killing when it has live + nodes registered. When running epmd interactively, + -relaxed_command_check has no effect. A daemon that is + started without relaxed command checking must be killed using, + for example, signals or some other OS-specific method if it has + active clients registered.

+
+ + +

Forcibly unregisters a live node from the epmd database.

+

This command can only be used when contacting epmd + instances started with flag -relaxed_command_check.

+

Notice that relaxed command checking must enabled for the + epmd daemon contacted. When running epmd + interactively, -relaxed_command_check has no effect.

+
+
+
- Environment variables + Environment Variables -

This environment variable may be set to a comma-separated - list of IP addresses, in which case the epmd daemon - will listen only on the specified address(es) and on the - loopback address (which is implicitly added to the list if it - has not been specified). The default behaviour is to listen on - all available IP addresses.

+

Can be set to a comma-separated + list of IP addresses, in which case the epmd daemon + will listen only on the specified address(es) and on the + loopback address (which is implicitly added to the list if it + has not been specified). The default behavior is to listen on + all available IP addresses.

-

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.

+

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.

-

If set prior to start, the epmd daemon will behave - as if the -relaxed_command_check option was given at - start-up. Consequently, if this option is set before starting - the Erlang virtual machine, the automatically started - epmd will accept the -kill and -stop - commands without restrictions.

+

If set before start, the epmd daemon behaves + as if option -relaxed_command_check was specified at + startup. Consequently, if this option is set before starting + the Erlang virtual machine, the automatically started + epmd accepts the -kill and -stop + commands without restrictions.

@@ -271,41 +289,45 @@
Logging

On some operating systems syslog will be used for - error reporting when epmd runs as an daemon. To enable - the error logging you have to edit /etc/syslog.conf - file and add an entry

+ error reporting when epmd runs as a daemon. To enable + the error logging, you must edit the + /etc/syslog.conf file and add an + entry:

+ /var/log/epmd.log - ]]> -

where <TABs> are at least one real tab character. Spaces will - silently be ignored. -

+ !epmd + *.*/var/log/epmd.log +]]>
+ +

where <TABs> are at least one real tab character. + Spaces are silently ignored.

+
- Access restrictions -

The epmd daemon accepts messages from both localhost and - remote hosts. However, only the query commands are answered (and - acted upon) if the query comes from a remote host. It is always an - error to try to register a nodename if the client is not a process - located on the same host as the epmd instance is running on- - such requests are considered hostile and the connection is - immediately closed.

+ Access Restrictions +

The epmd daemon accepts messages from both the local host and + remote hosts. However, only the query commands are answered (and + acted upon) if the query comes from a remote host. It is always an + error to try to register a node name if the client is not a process + on the same host as the epmd instance is running on. Such + requests are considered hostile and the connection is closed + immediately.

-

The queries accepted from remote nodes are:

- - -

Port queries - i.e. on which port does the node with a given - name listen

-
- -

Name listing - i.e. give a list of all names registered on +

The following queries are accepted from remote nodes:

+ + + +

Port queries, that is, on which port the node with a specified + name listens

+
+ +

Name listing, that is, gives a list of all names registered on the host

-
-
-

To restrict access further, firewall software has to be used.

-
+ + +

To restrict access further, firewall software must be used.

+
diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 37387f2c59..5559aec30e 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -30,86 +30,92 @@ erl.xml erl - The Erlang Emulator + The Erlang emulator.

The program starts an Erlang runtime system. - The exact details (for example, whether is a script or - a program and which other programs it calls) are system-dependent.

-

Windows users probably wants to use the program + The exact details (for example, whether is a + script or a program and which other programs it calls) are + system-dependent.

+ +

Windows users probably want to use the program instead, which runs in its own window with scrollbars and supports - command-line editing. The 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 program must be used, however, in pipelines or if + command-line editing. The program on Windows + provides no line editing in its shell, and on Windows 95 there is no way + to scroll back to text that has scrolled off the screen. The + program must be used, however, in pipelines or if you want to redirect standard input or output.

-

As of ERTS version 5.9 (OTP-R15B) the runtime system will by - default not bind schedulers to logical processors. - For more information see documentation of the - +sbt system flag. -

-
+ + +

As from ERTS 5.9 (Erlang/OTP R15B) the runtime system does by + default not bind schedulers to logical processors. + For more information, see system flag + +sbt.

+
+ erl <arguments> - Start an Erlang runtime system + Start an Erlang runtime system. -

Starts an Erlang runtime system.

-

The arguments can be divided into emulator flags, - flags and plain arguments:

- - -

Any argument starting with the character is - interpreted as an emulator flag.

-

As indicated by the name, emulator flags controls - the behavior of the emulator.

-
- -

Any argument starting with the character - (hyphen) is interpreted as a - flag which should - be passed to the Erlang part of the runtime system, more - specifically to the system process, see - init(3).

-

The process itself interprets some of these - flags, the init flags. It also stores any - remaining flags, the user flags. The latter can - be retrieved by calling .

-

It can be noted that there are a small number of "-" - flags which now actually are emulator flags, see - the description below.

-
- -

Plain arguments are not interpreted in any way. They are - also stored by the process and can be - retrieved by calling . - Plain arguments can occur before the first flag, or after - a flag. Additionally, the flag - causes everything that follows to become plain arguments.

-
-
-

Example:

-
+	

Starts an Erlang runtime system.

+

The arguments can be divided into emulator flags, + flags, and plain arguments:

+ + +

Any argument starting with character is + interpreted as an + emulator flag.

+

As indicated by the name, emulator flags control + the behavior of the emulator.

+
+ +

Any argument starting with character + (hyphen) is interpreted as a + flag, which is to + be passed to the Erlang part of the runtime system, more + specifically to the system process, see + init(3).

+

The process itself interprets some of + these flags, the init flags. It also stores any + remaining flags, the user flags. The latter can be + retrieved by calling .

+

A small number of "-" flags exist, which now actually are + emulator flags, see the description below.

+
+ +

Plain arguments are not interpreted in any way. They are also + stored by the process and can be retrieved + by calling . + Plain arguments can occur before the first flag, or after a + flag. Also, the + flag causes everything that follows to become plain arguments.

+
+
+

Examples:

+
 % erl +W w -sname arnie +R 9 -s my_init -extra +bertie
 (arnie@host)1> init:get_argument(sname).
 {ok,[["arnie"]]}
 (arnie@host)2> init:get_plain_arguments().
 ["+bertie"]
-

Here and are emulator flags. - is an init flag, interpreted by . - is a user flag, stored by . - It is read by Kernel and will cause the Erlang runtime system - to become distributed. Finally, everything after - (that is, ) is considered as plain arguments.

-
+        

Here and are + emulator flags. is an init flag, + interpreted by . + is a user flag, stored by + . It is read by Kernel and causes the + Erlang runtime system to become distributed. Finally, everything after + (that is, ) is + considered as plain arguments.

+
 % erl -myflag 1
 1> init:get_argument(myflag).
 {ok,[["1"]]}
 2> init:get_plain_arguments().
 []
-

Here the user flag is passed to and stored - by the process. It is a user defined flag, - presumably used by some user defined application.

+

Here the user flag is passed to and + stored by the process. It is a user-defined + flag, presumably used by some user-defined application.

@@ -117,50 +123,54 @@
Flags -

In the following list, init flags are marked (init flag). +

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 - . Note that the list of user flags is - not exhaustive, there may be additional, application specific - flags which instead are documented in the corresponding + . Notice that the list of user + flags is not exhaustive, there can be more application-specific + flags that instead are doscribed in the corresponding application documentation.

- (init flag) + (init flag)

Everything following up to the next flag - ( or ) is considered plain arguments - and can be retrieved using .

+ ( or ) is considered + plain arguments and can be retrieved using + .

-

Sets the application configuration parameter to - the value for the application , - see app(4) and - application(3).

+

Sets the application configuration parameter + to the value for the application + ; see + kernel:app(4) and + + kernel:application(3).

-

Command line arguments are read from the file . - The arguments read from the file replace the - '' flag on the resulting command line.

-

The file 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 are allowed, also the - flag. Be careful not to cause circular - dependencies between files containing the flag, - though.

-

The flag is treated specially. Its scope ends - at the end of the file. Arguments following an - flag are moved on the command line into the section, - i.e. the end of the command line following after an - flag.

+

Command-line arguments are read from the file + . The arguments read from the file replace + flag '' on the resulting + command line.

+

The file is to be a plain text file and + can contain comments and command-line arguments. A comment begins + with a # character and continues until the next end of line + character. Backslash (\\) is used as quoting character. All + command-line arguments accepted by are allowed, + also flag . Be careful not to + cause circular dependencies between files containing flag + , though.

+

The flag is treated in special way. Its + scope ends at the end of the file. Arguments following an + flag are moved on the command line into the + section, that is, the end of the command + line following after an flag.

The initial Erlang shell does not read user input until - the system boot procedure has been completed (Erlang 5.4 and + the system boot procedure has been completed (Erlang/OTP 5.4 and later). This flag disables the start synchronization feature and lets the shell start in parallel with the rest of the system.

@@ -168,52 +178,56 @@

Specifies the name of the boot file, , - which is used to start the system. See - init(3). Unless + which is used to start the system; see + init(3). Unless contains an absolute path, the system searches - for in the current and - directories.

+ for in the current and + directories.

Defaults to .

-

If the boot script contains a path variable other - than , this variable is expanded to . - Used when applications are installed in another directory - than , see - systools:make_script/1,2.

+

If the boot script contains a path variable + other than , this variable is expanded to + . Used when applications are installed in + another directory than ; see + + systools:make_script/1,2 in SASL.

-

Enables the code path cache of the code server, see - code(3).

+

Enables the code path cache of the code server; see + kernel:code(3).

Compiles the specified modules and then terminates (with non-zero exit code if the compilation of some file did not - succeed). Implies . Not recommended - use - erlc instead.

+ succeed). Implies .

+

Not recommended; use erlc + instead.

Specifies the name of a configuration file, , which is used to configure - applications. See - app(4) and - application(3).

+ applications; see + kernel:app(4) and + + kernel:application(3).

-

If this flag is present, will not maintain a - fully connected network of distributed Erlang nodes, and then - global name registration cannot be used. See - global(3).

+

If this flag is present, does not maintain + a fully connected network of distributed Erlang nodes, and then + global name registration cannot be used; see + kernel:global(3).

Obsolete flag without any effect and common misspelling for - . Use instead.

+ . Use + instead.

@@ -223,8 +237,7 @@ -

Useful for debugging. Prints out the actual arguments - sent to the emulator.

+

Useful for debugging. Prints the arguments sent to the emulator.

@@ -234,14 +247,16 @@
 % erl -env DISPLAY gin:0

In this example, an Erlang runtime system is started with - the environment variable set to .

+ environment variable set to + .

- (init flag) + (init flag) -

Makes evaluate the expression , see - init(3).

+

Makes evaluate the expression + ; see + init(3).

- (init flag) + (init flag)

Everything following is considered plain arguments and can be retrieved using @@ -249,8 +264,9 @@ -

Starts heart beat monitoring of the Erlang runtime system. - See heart(3).

+

Starts heartbeat monitoring of the Erlang runtime system; + see + kernel:heart(3).

@@ -258,91 +274,99 @@ run as a distributed node. Hidden nodes always establish hidden connections to all other nodes except for nodes in the same global group. Hidden connections are not published on - either of the connected nodes, i.e. neither of the connected - nodes are part of the result from on the other - node. See also hidden global groups, - global_group(3).

+ any of the connected nodes, that is, none of the connected + nodes are part of the result from on the + other node. See also hidden global groups; + + kernel:global_group(3).

-

Specifies the IP addresses for the hosts on which Erlang - boot servers are running, see - erl_boot_server(3). - This flag is mandatory if the flag is - present.

-

The IP addresses must be given in the standard form (four - decimal numbers separated by periods, for example - . Hosts names are not acceptable, but - a broadcast address (preferably limited to the local network) +

Specifies the IP addresses for the hosts on which Erlang boot servers + are running, see + kernel:erl_boot_server(3). This flag + is mandatory if flag is present.

+

The IP addresses must be specified in the standard form (four + decimal numbers separated by periods, for example, + . Hosts names are not acceptable, + but a broadcast address (preferably limited to the local network) is.

Specifies the identity of the Erlang runtime system. If it is run as a distributed node, must be identical to - the name supplied together with the or - flag.

+ the name supplied together with flag or + .

Makes write some debug information while interpreting the boot script.

- (emulator flag) + (emulator flag)

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 . + obtained and analyzed using the module. Functionally, it behaves exactly like an ordinary Erlang runtime system.

-

Specifies the method used by to load - Erlang modules into the system. See - erl_prim_loader(3). - Two methods are supported, and - . means use the local file system, - this is the default. means use a boot server on - another machine, and the , and - flags must be specified as well. If - is something else, the user supplied +

Specifies the method used by to + load Erlang modules into the system; see + erl_prim_loader(3). + Two methods are supported:

+ + +

, which means use the local file system, + this is the default.

+
+ +

, which means use a boot server on + another machine. The flags , + and must + also be specified.

+
+
+

If is something else, the user-supplied port program is started.

-

Makes the Erlang runtime system invoke in - the current working directory and then terminate. See - make(3). Implies +

Makes the Erlang runtime system invoke + in the current working directory and then terminate; see + tools:make(3). Implies .

-

Displays the manual page for the Erlang module . - Only supported on Unix.

+

Displays the manual page for the Erlang module + . Only supported on Unix.

-

Indicates if the system should load code dynamically - (), or if all code should be loaded - during system initialization (), see - code(3). Defaults to - .

+

Indicates if the system is to load code dynamically + (), or if all code is to be loaded + during system initialization (); see + kernel:code(3). + Defaults to .

Makes the Erlang runtime system into a distributed node. This flag invokes all network servers necessary for a node to - become distributed. See - net_kernel(3). - It is also ensured that runs on the current host - before Erlang is started. See - epmd(1) and the + become distributed; see + kernel:net_kernel(3). It is also ensured that + runs on the current host before Erlang is + started; see epmd(1).and the -start_epmd option.

-

The name of the node will be , where - is the fully qualified host name of the current - host. For short names, use the flag instead.

+

The node name will be , where + is the fully qualified host name of the + current host. For short names, use flag + instead.

@@ -353,115 +377,111 @@

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.

+ component in a series of Unix pipes.

Disables the sticky directory facility of the Erlang code - server, see - code(3).

+ server; see + kernel:code(3).

-

Invokes the old Erlang shell from Erlang 3.3. The old shell +

Invokes the old Erlang shell from Erlang/OTP 3.3. The old shell can still be used.

Adds the specified directories to the beginning of the code - path, similar to . See - code(3). + path, similar to ; see + kernel:code(3). As an alternative to -pa, if several directories are to be prepended to the code path and the directories have a - common parent directory, that parent directory could be - specified in the ERL_LIBS environment variable. - See code(3).

+ common parent directory, that parent directory can be + specified in environment variable ERL_LIBS; see + kernel:code(3).

Adds the specified directories to the end of the code path, - similar to . See - code(3).

+ similar to ; see + kernel:code(3).

-

Replaces the path specified in the boot script. See - script(4).

+

Replaces the path specified in the boot script; see + sasl:script(4).

-

Specify a protocol for Erlang distribution.

- - inet_tcp - -

TCP over IPv4 (the default)

-
- inet_tls - -

distribution over TLS/SSL

-
- inet6_tcp - -

TCP over IPv6

-
+

Specifies a protocol for Erlang distribution:

+ + inet_tcp + TCP over IPv4 (the default) + inet_tls + Distribution over TLS/SSL + inet6_tcp + TCP over IPv6

For example, to start up IPv6 distributed nodes:

-% erl -name test@ipv6node.example.com -proto_dist inet6_tcp
-
+% erl -name test@ipv6node.example.com -proto_dist inet6_tcp
-

Starts Erlang with a remote shell connected to .

+

Starts Erlang with a remote shell connected to + .

-

Specifies an alternative to for starting a slave - node on a remote host. See - slave(3).

+

Specifies an alternative to for starting a + slave node on a remote host; see + stdlib:slave(3).

- (init flag) + (init + flag) -

Makes call the specified function. - defaults to . 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 - as argument. All arguments are passed - as strings. See - init(3).

+

Makes call the specified function. + defaults to . + 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 + as argument. All arguments are + passed as strings. See + init(3).

- (init flag) + (init flag) -

Makes call the specified function. - defaults to . 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 - as argument. All arguments are passed - as atoms. See - init(3).

+

Makes call the specified function. + defaults to . + 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 + as argument. All arguments are + passed as atoms. See + init(3).

-

Sets the magic cookie of the node to , see - erlang:set_cookie/2.

+

Sets the magic cookie of the node to ; see + + erlang:set_cookie/2.

Specifies how long time (in milliseconds) the process is allowed to spend shutting down the system. If - ms have elapsed, all processes still existing are - killed. Defaults to .

+ milliseconds have elapsed, all processes still + existing are killed. Defaults to .

-

Makes the Erlang runtime system into a distributed node, - similar to , but the host name portion of the node +

Makes the Erlang runtime system into a distributed node, similar to + , but the host name portion of the node name will be the short name, not fully qualified.

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 - flag and those running with the flag, as node + the Domain Name System (DNS) is not running. No communication can + exist between nodes running with flag + and those running with flag , as node names must be unique in distributed Erlang systems.

-start_epmd true | false @@ -481,19 +501,21 @@ -

-smp enable and -smp starts the Erlang runtime - system with SMP support enabled. This may fail if no runtime +

-smp enable and -smp start the Erlang runtime + system with SMP support enabled. This can fail if no runtime system with SMP support is available. -smp auto starts the Erlang runtime system with SMP support enabled if it is - available and more than one logical processor are detected. + available and more than one logical processor is detected. -smp disable starts a runtime system without SMP support.

-

NOTE: The runtime system with SMP support will not - be available on all supported platforms. See also the - +S flag.

+ +

The runtime system with SMP support is not available on all + supported platforms. See also flag + +S.

+
- (emulator flag) + (emulator flag) -

Makes the emulator print out its version number. The same +

Makes the emulator print its version number. The same as .

@@ -505,133 +527,169 @@

invokes the code for the Erlang emulator (virtual machine), which supports the following flags:

- + +

Suggested stack size, in kilowords, for threads in the - async-thread pool. Valid range is 16-8192 kilowords. The - default suggested stack size is 16 kilowords, i.e, 64 + async thread pool. Valid range is 16-8192 kilowords. The + default suggested stack size is 16 kilowords, that is, 64 kilobyte on 32-bit architectures. This small default size - has been chosen since the amount of async-threads might - be quite large. The default size is enough for drivers - delivered with Erlang/OTP, but might not be sufficiently - large for other dynamically linked in drivers that use the - driver_async() - functionality. Note that the value passed is only a - suggestion, and it might even be ignored on some - platforms.

+ has been chosen because the number of async threads can + be large. The default size is enough for drivers + delivered with Erlang/OTP, but might not be large + enough for other dynamically linked-in drivers that use the + + driver_async() functionality. + Notice that the value passed is only a suggestion, + and it can even be ignored on some platforms.

-

Sets the number of threads in async thread pool, valid range - is 0-1024. If thread support is available, the default is 10.

+

Sets the number of threads in async thread pool. Valid range + is 0-1024. Defaults to 10 if thread support is available.

-

The option makes interrupt the current - shell instead of invoking the emulator break handler. - The option (same as specifying without an - extra option) disables the break handler. The option - makes the emulator ignore any break signal.

-

If the option is used with on Unix, - will restart the shell process rather than - interrupt it.

-

Note that on Windows, this flag is only applicable for - , not (). Note also that - is used instead of on Windows.

+

Option makes + interrupt the current shell instead of invoking the emulator break + handler. Option (same as specifying + without an extra option) disables the break + handler. Option makes the emulator ignore any + break signal.

+

If option is used with + on Unix, will + restart the shell process rather than interrupt it.

+

Notice that on Windows, this flag is only applicable for + , not + (). Notice also that + is used instead of + on Windows.

-

Enable or disable - time correction:

+

Enables or disables + time + correction:

true -

Enable time correction. This is the default if - time correction is supported on the specific platform.

- - false -

Disable time correction.

-
-

For backwards compatibility, the boolean value can be omitted. - This is interpreted as +c false. -

-
- - -

Set - time warp mode: -

- - no_time_warp -

No Time Warp Mode (the default)

- single_time_warp -

Single Time Warp Mode

- multi_time_warp -

Multi Time Warp Mode

-
+ Enables time correction. This is the default if + time correction is supported on the specific platform. + false + Disables time correction. +
+

For backward compatibility, the boolean value can be omitted. + This is interpreted as +c false.

+ + erlang:now()ime_warp | single_time_warp | + multi_time_warp]]> + +

Sets time warp + mode:

+ + no_time_warp + + No time warp mode (the default) + single_time_warp + + Single time warp mode + multi_time_warp + + Multi-time warp mode +

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.

- -

The +d option instructs the emulator to only produce a - core dump and no crash dump if an internal error is detected.

- -

Calling erlang:halt/1 with a string argument will still - produce a crash dump. On Unix systems, sending an emulator process - a SIGUSR1 signal will also force a crash dump.

+ it, by default, generates both a crash dump and a core dump. + The core dump is, however, not very useful as the content + of process heaps is destroyed by the crash dump generation.

+

Option +d instructs the emulator to produce only a + core dump and no crash dump if an internal error is detected.

+

Calling + erlang:halt/1 with a string argument still + produces a crash dump. On Unix systems, sending an emulator process + a SIGUSR1 signal also forces a crash dump.

-

Set max number of ETS tables.

+

Sets the maximum number of ets tables.

-

Force the compressed option on all ETS tables. - Only intended for test and evaluation.

+

Forces option compressed on all ets tables. + Only intended for test and evaluation.

- + + -

The VM works with file names as if they are encoded using the ISO-latin-1 encoding, disallowing Unicode characters with codepoints beyond 255.

-

See STDLIB User's Guide for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see STDLIB User's Guide).

+

The virtual machine works with filenames as if they are encoded + using the ISO Latin-1 encoding, disallowing Unicode characters with + code points > 255.

+

For more information about Unicode filenames, see section + Unicode + Filenames in the STDLIB User's Guide. Notice that + this value also applies to command-line parameters and environment + variables (see section + Unicode in Enviroment and Parameters in the STDLIB + User's Guide).

-

The VM works with file names as if they are encoded using - UTF-8 (or some other system specific Unicode encoding). This - is the default on operating systems that enforce Unicode - encoding, i.e. Windows and MacOS X.

-

The +fnu switch can be followed by w, - i, or e to control the way wrongly encoded file - names are to be reported. w means that a warning is - sent to the error_logger whenever a wrongly encoded - file name is "skipped" in directory listings, i means - that those wrongly encoded file names are silently ignored and - e means that the API function will return an error - whenever a wrongly encoded file (or directory) name is - encountered. w is the default. Note that - file:read_link/1 will always return an error if the - link points to an invalid file name.

-

See STDLIB User's Guide for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see STDLIB User's Guide).

+

The virtual machine works with filenames as if they are encoded + using UTF-8 (or some other system-specific Unicode encoding). This is + the default on operating systems that enforce Unicode encoding, that + is, Windows and MacOS X.

+

The +fnu switch can be followed by w, i, or + e to control how wrongly encoded filenames are to be + reported:

+ + +

w means that a warning is sent to the error_logger + whenever a wrongly encoded filename is "skipped" in directory + listings. This is the default.

+
+ +

i means that those wrongly encoded filenames are silently + ignored.

+
+ +

e means that the API function returns an error whenever a + wrongly encoded filename (or directory name) is encountered.

+
+
+

Notice that + file:read_link/1 always returns an error if the link + points to an invalid filename.

+

For more information about Unicode filenames, see section + Unicode + Filenames in the STDLIB User's Guide. Notice that + this value also applies to command-line parameters and environment + variables (see section + Unicode in Enviroment and Parameters in the STDLIB + User's Guide).

Selection between +fnl and +fnu is done based - on the current locale settings in the OS, meaning that if you - have set your terminal for UTF-8 encoding, the filesystem is - expected to use the same encoding for file names. This is - default on all operating systems except MacOS X and - Windows.

-

The +fna switch can be followed by w, - i, or e. This will have effect if the locale - settings cause the behavior of +fnu to be selected. - See the description of +fnu above. If the locale - settings cause the behavior of +fnl to be selected, - then w, i, or e will not have any - effect.

-

See STDLIB User's Guide for more infomation about unicode file names. Note that this value also applies to command-line parameters and environment variables (see STDLIB User's Guide).

+ on the current locale settings in the OS. This means that if you + have set your terminal for UTF-8 encoding, the filesystem is + expected to use the same encoding for filenames. This is + default on all operating systems, except MacOS X and Windows.

+

The +fna switch can be followed by w, i, or + e. This has effect if the locale settings cause the behavior + of +fnu to be selected; see the description of +fnu + above. If the locale settings cause the behavior of +fnl to be + selected, then w, i, or e have no effect.

+

For more information about Unicode filenames, see section + Unicode + Filenames in the STDLIB User's Guide. Notice that + this value also applies to command-line parameters and environment + variables (see section + Unicode in Enviroment and Parameters in the STDLIB + User's Guide).

@@ -646,26 +704,24 @@

Sets the default maximum heap size of processes to the size - . If +hmax is not given, the default is 0 - which means that no maximum heap size is used. - For more information, see the documentation of + . Defaults to 0, which means that no + maximum heap size is used. For more information, see - process_flag(max_heap_size, MaxHeapSize).

+ process_flag(max_heap_size, MaxHeapSize).

-

Sets whether to send an error logger message for processes that reach - the maximum heap size or not. If +hmaxel is not given, the default is true. - For more information, see the documentation of - +

Sets whether to send an error logger message or not for processes + reaching the maximum heap size. Defaults to true. + For more information, see + process_flag(max_heap_size, MaxHeapSize).

-

Sets whether to kill processes that reach the maximum heap size or not. If - +hmaxk is not given, the default is true. For more information, - see the documentation of - +

Sets whether to kill processes reaching the maximum heap size or not. + Default to true. For more information, see + process_flag(max_heap_size, MaxHeapSize).

@@ -674,304 +730,231 @@ .

+hmqd off_heap|on_heap -

- Sets the default value for the process flag - message_queue_data. If +hmqd is not - passed, on_heap will be the default. For more information, - see the documentation of - process_flag(message_queue_data, - MQD). -

+ +

Sets the default value for process flag message_queue_data. + Defaults to on_heap. If +hmqd is not + passed, on_heap will be the default. For more information, see + + process_flag(message_queue_data, MQD).

+
-

Enables or disables the kernel poll functionality if - the emulator supports it. Default is (disabled). - If the emulator does not support kernel poll, and - the flag is passed to the emulator, a warning is +

Enables or disables the kernel poll functionality if supported by + the emulator. Defaults to (disabled). + If the emulator does not support kernel poll, and flag + is passed to the emulator, a warning is issued at startup.

-

Enables auto load tracing, displaying info while loading +

Enables autoload tracing, displaying information while loading code.

-

Don't load information about source file names and line numbers. - This will save some memory, but exceptions will not contain - information about the file names and line numbers. -

+

Prevents loading information about source filenames and line + numbers. This saves some memory, but exceptions do not contain + information about the filenames and line numbers.

-

Memory allocator specific flags, see - erts_alloc(3) for - further information.

-
- - -

Control behavior of signals to ports.

-

As of OTP-R16 signals to ports are truly asynchronously - delivered. Note that signals always have been documented as - asynchronous. The underlying implementation has, however, - previously delivered these signals synchronously. Correctly - written Erlang programs should be able to handle this without - any issues. Bugs in existing Erlang programs that make false - assumptions about signals to ports may, however, be tricky to - find. This switch has been introduced in order to at least - make it easier to compare behaviors during a transition period. - Note that this flag is deprecated as of its - introduction, and is scheduled for removal in OTP-R17. - Behavior should be one of the following characters:

- - d - The default. Asynchronous signals. A process that sends - a signal to a port may continue execution before the signal - has been delivered to the port. - s - Synchronous signals. A processes that sends a signal - to a port will not continue execution until the signal has - been delivered. Should only be used for testing and - debugging. - a - Asynchronous signals. As the default, but a processes - that sends a signal will even more frequently continue - execution before the signal has been delivered to the - port. Should only be used for testing and - debugging. - -
- - -

Sets the range of characters that the system will consider printable in heuristic detection of strings. This typically affects the shell, debugger and io:format functions (when ~tp is used in the format string).

-

Currently two values for the Range are supported:

- - latin1 The default. Only characters - in the ISO-latin-1 range can be considered printable, which means - that a character with a code point > 255 will never be - considered printable and that lists containing such - characters will be displayed as lists of integers rather - than text strings by tools. - unicode - All printable Unicode characters are considered when - determining if a list of integers is to be displayed in - string syntax. This may give unexpected results if for - example your font does not cover all Unicode - characters. - -

Se also - io:printable_range/0.

-
- - -

Sets the maximum number of simultaneously existing processes for this - system if a Number is passed as value. Valid range for - Number is [1024-134217727]

-

NOTE: The actual maximum chosen may be much larger than - the Number passed. Currently the runtime system often, - but not always, chooses a value that is a power of 2. This might, - however, be changed in the future. The actual value chosen can be - checked by calling - erlang:system_info(process_limit).

-

The default value is 262144

-

If legacy is passed as value, the legacy algorithm for - allocation of process identifiers will be used. Using the legacy - algorithm, identifiers will be allocated in a strictly increasing - fashion until largest possible identifier has been reached. Note that - this algorithm suffers from performance issues and can under certain - circumstances be extremely expensive. The legacy algoritm is deprecated, - and the legacy option is scheduled for removal in OTP-R18.

-
- - -

Sets the maximum number of simultaneously existing ports for this - system if a Number is passed as value. Valid range for Number - is [1024-134217727]

-

NOTE: The actual maximum chosen may be much larger than - the actual Number passed. Currently the runtime system often, - but not always, chooses a value that is a power of 2. This might, - however, be changed in the future. The actual value chosen can be - checked by calling - erlang:system_info(port_limit).

-

The default value used is normally 65536. However, if - the runtime system is able to determine maximum amount of file - descriptors that it is allowed to open and this value is larger - than 65536, the chosen value will increased to a value - larger or equal to the maximum amount of file descriptors that - can be opened.

-

On Windows the default value is set to 8196 because the - normal OS limitations are set higher than most machines can handle.

-

Previously the environment variable ERL_MAX_PORTS was used - for setting the maximum number of simultaneously existing ports. This - environment variable is deprecated, and scheduled for removal in - OTP-R17, but can still be used.

-

If legacy is passed as value, the legacy algorithm for - allocation of port identifiers will be used. Using the legacy - algorithm, identifiers will be allocated in a strictly increasing - fashion until largest possible identifier has been reached. Note that - this algorithm suffers from performance issues and can under certain - circumstances be extremely expensive. The legacy algoritm is deprecated, - and the legacy option is scheduled for removal in OTP-R18.

+

Memory allocator-specific flags. For more information, see + erts_alloc(3).

+
+ + + +

Sets the range of characters that the system considers printable in + heuristic detection of strings. This typically affects the shell, + debugger, and io:format functions (when ~tp is used in + the format string).

+

Two values are supported for Range:

+ + latin1 + The default. Only characters in the ISO Latin-1 range can be + considered printable. This means that a character with a code point + > 255 is never considered printable and that lists containing + such characters are displayed as lists of integers rather than text + strings by tools. + unicode + All printable Unicode characters are considered when + determining if a list of integers is to be displayed in + string syntax. This can give unexpected results if, for + example, your font does not cover all Unicode characters. + +

See also + io:printable_range/0 in STDLIB.

Sets the compatibility mode.

-

The distribution mechanism is not backwards compatible by - default. This flags sets the emulator in compatibility mode +

The distribution mechanism is not backward compatible by + default. This flag sets the emulator in compatibility mode with an earlier Erlang/OTP release . The release number must be in the range -2..]]>. 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.

-

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 - all Y nodes have compatibility mode X.

+ limits the emulator, making it possible for it to communicate + with Erlang nodes (as well as C- and Java nodes) running that + earlier release.

+ +

Ensure that all nodes (Erlang-, C-, and Java nodes) of + a distributed Erlang system is of the same Erlang/OTP release, + or from two different Erlang/OTP releases X and Y, where + all Y nodes have compatibility mode X.

+
-

Force ets memory block to be moved on realloc.

+

Forces ets memory block to be moved on realloc.

-

Limits the amount of reader groups used by read/write locks - optimized for read operations in the Erlang runtime system. By - default the reader groups limit equals 64.

-

When the amount of schedulers is less than or equal to the reader - groups limit, each scheduler has its own reader group. When the - amount of schedulers is larger than the reader groups limit, - schedulers share reader groups. Shared reader groups degrades - read lock and read unlock performance while a large amount of - reader groups degrades write lock performance, so the limit is a - tradeoff between performance for read operations and performance - for write operations. Each reader group currently consumes 64 byte - in each read/write lock. Also note that a runtime system using - shared reader groups benefits from binding - schedulers to logical processors, since the reader groups - are distributed better between schedulers.

-
- - -

Sets the number of scheduler threads to create and scheduler - threads to set online when SMP support has been enabled. The maximum for - both values is 1024. If the Erlang runtime system is able to determine the - amount of logical processors configured and logical processors available, - Schedulers will default to logical processors configured, and - SchedulersOnline will default to logical processors available; - otherwise, the default values will be 1. Schedulers may be omitted - if :SchedulerOnline is not and vice versa. The number of schedulers - online can be changed at run time via - erlang:system_flag(schedulers_online, SchedulersOnline). -

-

If Schedulers or SchedulersOnline is specified as a - negative number, the value is subtracted from the default number of - logical processors configured or logical processors available, respectively. -

-

Specifying the value 0 for Schedulers or SchedulersOnline - resets the number of scheduler threads or scheduler threads online respectively - to its default value. -

-

This option is ignored if the emulator doesn't have - SMP support enabled (see the -smp - flag).

-
- - -

Similar to +S but uses percentages to set the - number of scheduler threads to create, based on logical processors configured, - and scheduler threads to set online, based on logical processors available, when - SMP support has been enabled. Specified values must be greater than 0. For example, - +SP 50:25 sets the number of scheduler threads to 50% of the logical processors - configured and the number of scheduler threads online to 25% of the logical processors available. - SchedulersPercentage may be omitted if :SchedulersOnlinePercentage is - not and vice versa. The number of schedulers online can be changed at run time via - erlang:system_flag(schedulers_online, SchedulersOnline). -

-

This option interacts with +S settings. - For example, on a system with 8 logical cores configured and 8 logical cores - available, the combination of the options +S 4:4 +SP 50:25 (in either order) - results in 2 scheduler threads (50% of 4) and 1 scheduler thread online (25% of 4). -

-

This option is ignored if the emulator doesn't have - SMP support enabled (see the -smp - flag).

-
- - -

Sets the number of dirty CPU scheduler threads to create and dirty - CPU scheduler threads to set online when threading support has been - enabled. The maximum for both values is 1024, and each value is further - limited by the settings for normal schedulers: the number of dirty CPU - scheduler threads created cannot exceed the number of normal scheduler - threads created, and the number of dirty CPU scheduler threads online - cannot exceed the number of normal scheduler threads online (see the - +S and +SP - flags for more details). By default, the number of dirty CPU scheduler - threads created equals the number of normal scheduler threads created, - and the number of dirty CPU scheduler threads online equals the number - of normal scheduler threads online. DirtyCPUSchedulers may be - omitted if :DirtyCPUSchedulersOnline is not and vice versa. The - number of dirty CPU schedulers online can be changed at run time via - erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline). -

-

- The amount of dirty CPU schedulers is limited by the amount of - normal schedulers in order to limit the effect on processes - executing on ordinary schedulers. If the amount of dirty CPU - schedulers was allowed to be unlimited, dirty CPU bound jobs would - potentially starve normal jobs. -

-

This option is ignored if the emulator doesn't have threading support - enabled. Currently, this option is experimental and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). -

-
- - -

Similar to +SDcpu but uses percentages to set the - number of dirty CPU scheduler threads to create and number of dirty CPU scheduler threads - to set online when threading support has been enabled. Specified values must be greater - than 0. For example, +SDPcpu 50:25 sets the number of dirty CPU scheduler threads - to 50% of the logical processors configured and the number of dirty CPU scheduler threads - online to 25% of the logical processors available. DirtyCPUSchedulersPercentage may - be omitted if :DirtyCPUSchedulersOnlinePercentage is not and vice versa. The - number of dirty CPU schedulers online can be changed at run time via - erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline). -

-

This option interacts with +SDcpu settings. - For example, on a system with 8 logical cores configured and 8 logical cores available, - the combination of the options +SDcpu 4:4 +SDPcpu 50:25 (in either order) results - in 2 dirty CPU scheduler threads (50% of 4) and 1 dirty CPU scheduler thread online (25% of 4). -

-

This option is ignored if the emulator doesn't have threading support - enabled. Currently, this option is experimental and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). -

+

Limits the number of reader groups used by read/write locks + optimized for read operations in the Erlang runtime system. By + default the reader groups limit is 64.

+

When the number of schedulers is less than or equal to the reader + groups limit, each scheduler has its own reader group. When the + number of schedulers is larger than the reader groups limit, + schedulers share reader groups. Shared reader groups degrade + read lock and read unlock performance while many + reader groups degrade write lock performance. So, the limit is a + tradeoff between performance for read operations and performance + for write operations. Each reader group consumes 64 byte + in each read/write lock.

+

Notice that a runtime system using shared reader groups benefits from + binding schedulers to logical + processors, as the reader groups are distributed better + between schedulers.

+
+ + + +

Sets the number of scheduler threads to create and scheduler threads + to set online when SMP support has been enabled. The maximum for both + values is 1024. If the Erlang runtime system is able to determine the + number of logical processors configured and logical processors + available, Schedulers defaults to logical processors + configured, and SchedulersOnline defaults to logical processors + available; otherwise the default values are 1. Schedulers can + be omitted if :SchedulerOnline is not and conversely. The + number of schedulers online can be changed at runtime through + + erlang:system_flag(schedulers_online, + SchedulersOnline).

+

If Schedulers or SchedulersOnline is specified as a + negative number, the value is subtracted from the default number of + logical processors configured or logical processors available, + respectively.

+

Specifying value 0 for Schedulers or + SchedulersOnline resets the number of scheduler threads or + scheduler threads online, respectively, to its default value.

+

This option is ignored if the emulator does not have SMP support + enabled (see flag -smp).

+
+ + +

Similar to +S but uses + percentages to set the number of scheduler threads to create, based + on logical processors configured, and scheduler threads to set online, + based on logical processors available, when SMP support has been + enabled. Specified values must be > 0. For example, + +SP 50:25 sets the number of scheduler threads to 50% of the + logical processors configured, and the number of scheduler threads + online to 25% of the logical processors available. + SchedulersPercentage can be omitted if + :SchedulersOnlinePercentage is not and conversely. The number + of schedulers online can be changed at runtime through + + erlang:system_flag(schedulers_online, + SchedulersOnline).

+

This option interacts with +S + settings. For example, on a system with 8 logical cores configured + and 8 logical cores available, the combination of the options + +S 4:4 +SP 50:25 (in either order) results in 2 scheduler + threads (50% of 4) and 1 scheduler thread online (25% of 4).

+

This option is ignored if the emulator does not have SMP support + enabled (see flag -smp).

+
+ + +

Sets the number of dirty CPU scheduler threads to create and dirty + CPU scheduler threads to set online when threading support has been + enabled. The maximum for both values is 1024, and each value is + further limited by the settings for normal schedulers:

+ + The number of dirty CPU scheduler threads created cannot exceed + the number of normal scheduler threads created. + The number of dirty CPU scheduler threads online cannot exceed + the number of normal scheduler threads online. + +

For details, see the +S and + +SP. By default, the number + of dirty CPU scheduler threads created equals the number of normal + scheduler threads created, and the number of dirty CPU scheduler + threads online equals the number of normal scheduler threads online. + DirtyCPUSchedulers can be omitted if + :DirtyCPUSchedulersOnline is not and conversely. The number of + dirty CPU schedulers online can be changed at runtime through + + erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline).

+

The amount of dirty CPU schedulers is limited by the amount of + normal schedulers in order to limit the effect on processes + executing on ordinary schedulers. If the amount of dirty CPU + schedulers was allowed to be unlimited, dirty CPU bound jobs would + potentially starve normal jobs.

+

This option is ignored if the emulator does not have threading + support enabled. This option is experimental and + is supported only if the emulator was configured and built with + support for dirty schedulers enabled (it is disabled by default).

+
+ + +

Similar to +SDcpu but + uses percentages to set the number of dirty CPU scheduler threads to + create and the number of dirty CPU scheduler threads to set online + when threading support has been enabled. Specified values must be + > 0. For example, +SDPcpu 50:25 sets the number of dirty + CPU scheduler threads to 50% of the logical processors configured + and the number of dirty CPU scheduler threads online to 25% of the + logical processors available. DirtyCPUSchedulersPercentage can + be omitted if :DirtyCPUSchedulersOnlinePercentage is not and + conversely. The number of dirty CPU schedulers online can be changed + at runtime through + + erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline).

+

This option interacts with +SDcpu settings. For example, on a + system with 8 logical cores configured and 8 logical cores available, + the combination of the options +SDcpu 4:4 +SDPcpu 50:25 (in + either order) results in 2 dirty CPU scheduler threads (50% of 4) and + 1 dirty CPU scheduler thread online (25% of 4).

+

This option is ignored if the emulator does not have threading + support enabled. This option is experimental and + is supported only if the emulator was configured and built with + support for dirty schedulers enabled (it is disabled by default).

-

Sets the number of dirty I/O scheduler threads to create when threading - support has been enabled. The valid range is 0-1024. By default, the number - of dirty I/O scheduler threads created is 10, same as the default number of - threads in the async thread pool - . -

-

- The amount of dirty IO schedulers is not limited by the amount of - normal schedulers like the amount of - dirty CPU schedulers. This since only I/O bound work is - expected to execute on dirty I/O schedulers. If the user should schedule CPU - bound jobs on dirty I/O schedulers, these jobs might starve ordinary - jobs executing on ordinary schedulers. -

-

This option is ignored if the emulator doesn't have threading support - enabled. Currently, this option is experimental and is supported only - if the emulator was configured and built with support for dirty schedulers - enabled (it's disabled by default). -

+

Sets the number of dirty I/O scheduler threads to create when + threading support has been enabled. Valid range is 0-1024. By + default, the number of dirty I/O scheduler threads created is 10, + same as the default number of threads in the async thread pool.

+

The amount of dirty IO schedulers is not limited by the amount of + normal schedulers like the amount of + dirty CPU schedulers. This since only I/O bound work is + expected to execute on dirty I/O schedulers. If the user should schedule CPU + bound jobs on dirty I/O schedulers, these jobs might starve ordinary + jobs executing on ordinary schedulers.

+

This option is ignored if the emulator does not have threading + support enabled. This option is experimental and + is supported only if the emulator was configured and built with + support for dirty schedulers enabled (it is disabled by default).

@@ -979,238 +962,237 @@ +sbt BindType -

Set scheduler bind type.

-

Schedulers can also be bound using the - +stbt flag. The only difference - between these two flags is how the following errors are handled:

- - Binding of schedulers is not supported on the specific - platform. - No available CPU topology. That is the runtime system - was not able to automatically detected the CPU topology, and - no user defined CPU topology - was set. - -

If any of these errors occur when +sbt has been passed, - the runtime system will print an error message, and refuse to - start. If any of these errors occur when +stbt has been - passed, the runtime system will silently ignore the error, and - start up using unbound schedulers.

-

Currently valid BindTypes: -

- - u - -

unbound - 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.

+

Sets scheduler bind type.

+

Schedulers can also be bound using flag + +stbt. The only + difference between these two flags is how the following errors + are handled:

+ + Binding of schedulers is not supported on the specific + platform. + No available CPU topology. That is, the runtime system was + not able to detect the CPU topology automatically, and no + user-defined CPU topology + was set. + +

If any of these errors occur when +sbt has been passed, + the runtime system prints an error message, and refuses to + start. If any of these errors occur when +stbt has been + passed, the runtime system silently ignores the error, and + start up using unbound schedulers.

+

Valid BindTypes:

+ + u + unbound - Schedulers are not bound to logical + processors, that is, the operating system decides where the + scheduler threads execute, and when to migrate them. This is + the default. - ns - -

no_spread - Schedulers with close scheduler - identifiers will be bound as close as possible in hardware.

+ ns + no_spread - Schedulers with close scheduler + identifiers are bound as close as possible in hardware. - ts - -

thread_spread - Thread refers to hardware threads - (e.g. Intel's hyper-threads). Schedulers with low scheduler - identifiers, will be bound to the first hardware thread of - each core, then schedulers with higher scheduler identifiers - will be bound to the second hardware thread of each core, - etc.

+ ts + thread_spread - Thread refers to hardware threads + (such as Intel's hyper-threads). Schedulers with low scheduler + identifiers, are bound to the first hardware thread of + each core, then schedulers with higher scheduler identifiers + are bound to the second hardware thread of each core,and so on. - ps - -

processor_spread - Schedulers will be spread like - thread_spread, but also over physical processor chips.

+ ps + processor_spread - Schedulers are spread like + thread_spread, but also over physical processor chips. - s - -

spread - Schedulers will be spread as much as - possible.

+ s + spread - Schedulers are spread as much as possible. - nnts - -

no_node_thread_spread - Like thread_spread, - 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.

+ nnts + no_node_thread_spread - Like thread_spread, + but if multiple Non-Uniform Memory Access (NUMA) nodes exist, + schedulers are spread over one NUMA node at a time, + that is, all logical processors of one NUMA node are bound + to schedulers in sequence. - nnps - -

no_node_processor_spread - Like - processor_spread, 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.

+ nnps + no_node_processor_spread - Like + processor_spread, but if multiple NUMA nodes exist, + schedulers are spread over one NUMA node at a time, that is, + all logical processors of one NUMA node are bound to + schedulers in sequence. - tnnps - -

thread_no_node_processor_spread - A combination of - thread_spread, and no_node_processor_spread. - 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.

+ tnnps + thread_no_node_processor_spread - A combination of + thread_spread, and no_node_processor_spread. + Schedulers are spread over hardware threads across NUMA + nodes, but schedulers are only spread over processors + internally in one NUMA node at a time. - db - -

default_bind - Binds schedulers the default way. - Currently the default is thread_no_node_processor_spread - (which might change in the future).

+ db + default_bind - Binds schedulers the default way. + Defaults to thread_no_node_processor_spread + (which can change in the future). -
-

Binding of schedulers is currently only supported on newer - Linux, Solaris, FreeBSD, and Windows systems.

-

If no CPU topology is available when the +sbt flag - is processed and BindType is any other type than - u, the runtime system will fail to start. CPU - topology can be defined using the - +sct flag. Note - that the +sct flag may have to be passed before the - +sbt flag on the command line (in case no CPU topology - has been automatically detected).

-

The runtime system will by default not bind schedulers - to logical processors. -

-

NOTE: If the Erlang runtime system is the only operating system - process that binds threads to logical processors, this - improves the performance of the runtime system. However, - if other operating system processes (as for example - another Erlang runtime system) also bind threads to - logical processors, there might be a performance penalty - instead. In some cases this performance penalty might be - severe. If this is the case, you are advised to not - bind the schedulers.

+
+

Binding of schedulers is only supported on newer + Linux, Solaris, FreeBSD, and Windows systems.

+

If no CPU topology is available when flag +sbt + is processed and BindType is any other type than + u, the runtime system fails to start. CPU + topology can be defined using flag + +sct. Notice + that flag +sct can have to be passed before flag + +sbt on the command line (if no CPU topology + has been automatically detected).

+

The runtime system does by default not bind schedulers + to logical processors.

+ +

If the Erlang runtime system is the only operating system + process that binds threads to logical processors, this + improves the performance of the runtime system. However, + if other operating system processes (for example + another Erlang runtime system) also bind threads to + logical processors, there can be a performance penalty + instead. This performance penalty can sometimes be + severe. If so, you are advised not to + bind the schedulers.

+

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. -

-

- NOTE: 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 - error_logger. If you want to verify that the - schedulers actually have bound as requested, call - erlang:system_info(scheduler_bindings). -

+ situations when there are fewer running processes than + schedulers online, the runtime system tries to migrate + processes to schedulers with low scheduler identifiers. + The more the schedulers are spread over the hardware, + the more resources are available to the runtime + system in such situations.

+ +

If a scheduler fails to bind, this is + often silently ignored, as it is not always + possible to verify valid logical processor identifiers. If + an error is reported, it is reported to the + error_logger. If you want to verify that the + schedulers have bound as requested, call + + erlang:system_info(scheduler_bindings).

+
- +sbwt none|very_short|short|medium|long|very_long - -

Set scheduler busy wait threshold. Default is medium. - The threshold determines how long schedulers should busy - wait when running out of work before going to sleep. -

-

NOTE: This flag may be removed or changed at any time - without prior notice. -

-
- +scl true|false + + +sbwt none|very_short|short|medium|long|very_long + +

Sets scheduler busy wait threshold. Defaults to medium. + The threshold determines how long schedulers are to busy + wait when running out of work before going to sleep.

+ +

This flag can be removed or changed at any time + without prior notice.

+
+
++scl true|false -

Enable or disable scheduler compaction of load. By default - scheduler compaction of load is enabled. When enabled, load - balancing will strive for a load distribution which causes - as many scheduler threads as possible to be fully loaded (i.e., - not run out of work). This is accomplished by migrating load - (e.g. runnable processes) into a smaller set of schedulers - when schedulers frequently run out of work. When disabled, - the frequency with which schedulers run out of work will - not be taken into account by the load balancing logic. -
  +scl false is similar to - +sub true with the difference - that +sub true also will balance scheduler utilization - between schedulers. -

+

Enables or disables scheduler compaction of load. By default + scheduler compaction of load is enabled. When enabled, load + balancing strives for a load distribution, which causes + as many scheduler threads as possible to be fully loaded (that is, + not run out of work). This is accomplished by migrating load + (for example, runnable processes) into a smaller set of schedulers + when schedulers frequently run out of work. When disabled, + the frequency with which schedulers run out of work is + not taken into account by the load balancing logic.

+

+scl false is similar to + +sub true, but + +sub true also balances scheduler utilization + between schedulers.

+sct CpuTopology - = integer(); when 0 =< =< 65535]]> + = integer(); when 0 =< =< 65535]]> + = -]]> = | ]]> - = , | ]]> + = , | + ]]> = L]]> - = T | t]]> + = T | t]]> + = C | c]]> - = P | p]]> + = P | p]]> + = N | n]]> - = | ]]> - : | ]]> + = + | + ]]> + + : | + ]]> + +

Sets a user-defined CPU topology. The user-defined + CPU topology overrides any automatically detected + CPU topology. The CPU topology is used when + binding schedulers to logical + processors.

+

Uppercase letters signify real identifiers and lowercase + letters signify fake identifiers only used for description + of the topology. Identifiers passed as real identifiers can + be used by the runtime system when trying to access specific + hardware; if they are incorrect the behavior is + undefined. Faked logical CPU identifiers are not accepted, + as there is no point in defining the CPU topology without + real logical CPU identifiers. Thread, core, processor, and + node identifiers can be omitted. If omitted, the thread ID + defaults to t0, the core ID defaults to c0, + the processor ID defaults to p0, and the node ID is + left undefined. Either each logical processor must + belong to only one NUMA node, or no logical + processors must belong to any NUMA nodes.

+

Both increasing and decreasing ]]>s + are allowed.

+

NUMA node identifiers are system wide. That is, each NUMA + node on the system must have a unique identifier. Processor + identifiers are also system wide. Core identifiers are + processor wide. Thread identifiers are core wide.

+

The order of the identifier types implies the hierarchy of the + CPU topology. The valid orders are as follows:

+ + +

]]>, + that is, thread is part of a core that is part of a processor, + which is part of a NUMA node.

+
+ +

]]>, + that is, thread is part of a core that 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 only one NUMA node. If + ]]> is omitted, its default position + is before ]]>. That is, the default is + processor external NUMA nodes.

+

If a list of identifiers is used in an + ]]>:

+ + ]]> must be a list + of identifiers. + At least one other identifier type besides + ]]> must also have a + list of identifiers. + All lists of identifiers must produce the + same number of identifiers. -

Set a user defined CPU topology. The user defined - CPU topology will override any automatically detected - CPU topology. The CPU topology is used when - binding schedulers to logical - processors. -

-

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 t0, core id defaults to c0, - processor id defaults to p0, 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. -

-

Both increasing and decreasing ]]>s - are allowed.

-

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.

-

The order of the identifier types imply the hierarchy of the - CPU topology. Valid orders are either - ]]>, - or - ]]>. - 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 ]]> - is left out, its default position will be before - ]]>. That is, the default is - processor external NUMA nodes. -

-

If a list of identifiers is used in an - ]]>:

- - ]]> have to be a list - of identifiers. - At least one other identifier type apart from - ]]> also have to have a - list of identifiers. - All lists of identifiers have to produce the - same amount of identifiers. - -

A simple example. A single quad core processor may be - described this way:

+

A simple example. A single quad core processor can be + described as follows:

 % erl +sct L0-3c0-3
 1> erlang:system_info(cpu_topology).
 [{processor,[{core,{logical,0}},
              {core,{logical,1}},
              {core,{logical,2}},
-             {core,{logical,3}}]}]
-
-

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:

+ {core,{logical,3}}]}]
+

A more complicated example with two quad core + processors, each processor in its own NUMA node. + The ordering of logical processors is a bit weird. + This to give a better example of identifier lists:

 % erl +sct L0-1,3-2c0-3p0N0:L7,4,6-5c0-3p1N1
 1> erlang:system_info(cpu_topology).
@@ -1221,239 +1203,247 @@
  {node,[{processor,[{core,{logical,7}},
                     {core,{logical,4}},
                     {core,{logical,6}},
-                    {core,{logical,5}}]}]}]
-
-

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:

+ {core,{logical,5}}]}]}] +

As long as real identifiers are correct, it is OK + to pass a CPU topology that is not a correct + description of the CPU topology. When used with + care this can be very useful. This + to trick the emulator to bind its schedulers + as you want. For example, if you want to run multiple + Erlang runtime systems on the same machine, you + want to reduce the number of schedulers used and + manipulate the CPU topology so that they bind to + different logical CPUs. An example, with two Erlang + runtime systems on a quad core machine:

 % erl +sct L0-3c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname one
-% erl +sct L3-0c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname two
-
-

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.

-

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.

-

For more information, see - erlang:system_info(cpu_topology).

+% erl +sct L3-0c0-3 +sbt db +S3:2 -detached -noinput -noshell -sname two +

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.

+

Notice that a faked CPU topology that does not reflect + how the real CPU topology looks like is likely to + decrease the performance of the runtime system.

+

For more information, see + + erlang:system_info(cpu_topology).

+secio true|false -

Enable or disable eager check I/O scheduling. The default - is currently true. The default was changed from false - to true as of erts version 7.0. The behaviour before this - flag was introduced corresponds to +secio false.

-

The flag effects when schedulers will check for I/O - operations possible to execute, and when such I/O operations - will execute. As the name of the parameter implies, - schedulers will be more eager to check for I/O when - true is passed. This however also implies that - execution of outstanding I/O operation will not be - prioritized to the same extent as when false is - passed.

-

erlang:system_info(eager_check_io) - returns the value of this parameter used when starting the VM.

+

Enables or disables eager check I/O scheduling. Defaults + to true. The default was changed from false + as from ERTS 7.0. The behavior before this + flag was introduced corresponds to +secio false.

+

The flag effects when schedulers will check for I/O + operations possible to execute, and when such I/O operations + will execute. As the parameter name implies, + schedulers are more eager to check for I/O when + true is passed. This, however, also implies that + execution of outstanding I/O operation is not + prioritized to the same extent as when false is + passed.

+

+ erlang:system_info(eager_check_io) + returns the value of this parameter used when starting + the virtual machine.

+sfwi Interval -

Set scheduler forced wakeup interval. All run queues will - be scanned each Interval milliseconds. While there are - sleeping schedulers in the system, one scheduler will be woken - for each non-empty run queue found. An Interval of zero - disables this feature, which also is the default. -

-

This feature has been introduced as a temporary workaround - for long-executing native code, and native code that does not - bump reductions properly in OTP. When these bugs have be fixed - the +sfwi flag will be removed. -

-
+

Sets scheduler-forced wakeup interval. All run queues are + scanned each Interval milliseconds. While there are + sleeping schedulers in the system, one scheduler is woken + for each non-empty run queue found. Interval default + to 0, meaning this feature is disabled.

+ +

This feature has been introduced as a temporary workaround + for long-executing native code, and native code that does not + bump reductions properly in OTP. When these bugs have be fixed, + this flag will be removed.

+
+ + +spp Bool + +

Sets default scheduler hint for port parallelism. If set to + true, the virtual machine schedules port tasks when it + improves parallelism in the system. If set to false, the + virtual machine tries to perform port tasks immediately, + improving latency at the expense of parallelism. Default to + false. The default used can be inspected in runtime by + calling + erlang:system_info(port_parallelism). + The default can be overridden on port creation by passing option + + parallelism to + + erlang:open_port/2

. +
+ + + +

Suggested stack size, in kilowords, for scheduler threads. + Valid range is 4-8192 kilowords. The default stack size is + OS-dependent.

+
+stbt BindType -

Try to set scheduler bind type. The same as the - +sbt flag with the exception of - how some errors are handled. For more information, see the - documentation of the +sbt flag. -

-
+

Tries to set the scheduler bind type. The same as flag + +sbt except + how some errors are handled. For more information, see + +sbt.

+ +sub true|false -

Enable or disable - scheduler - utilization balancing of load. By default scheduler - utilization balancing is disabled and instead scheduler - compaction of load is enabled which will strive for a load - distribution which causes as many scheduler threads as possible - to be fully loaded (i.e., not run out of work). When scheduler - utilization balancing is enabled the system will instead try to - balance scheduler utilization between schedulers. That is, - strive for equal scheduler utilization on all schedulers. -
   +sub true is only supported on - systems where the runtime system detects and uses a monotonically - increasing high resolution clock. On other systems, the runtime - system will fail to start. -
   +sub true implies - +scl false. The difference - between +sub true and +scl false is that - +scl false will not try to balance the scheduler - utilization. -

+

Enables or disables + + scheduler utilization balancing of load. By default + scheduler utilization balancing is disabled and instead scheduler + compaction of load is enabled, which strives for a load + distribution that causes as many scheduler threads as possible + to be fully loaded (that is, not run out of work). When scheduler + utilization balancing is enabled, the system instead tries to + balance scheduler utilization between schedulers. That is, + strive for equal scheduler utilization on all schedulers.

+

+sub true is only supported on systems where the runtime + system detects and uses a monotonically increasing high-resolution + clock. On other systems, the runtime system fails to start.

+

+sub true implies + +scl false. The difference between + +sub true and +scl false is that +scl false + does not try to balance the scheduler utilization.

- +swct very_eager|eager|medium|lazy|very_lazy - -

- Set scheduler wake cleanup threshold. Default is medium. - This flag controls how eager schedulers should be requesting - wake up due to certain cleanup operations. When a lazy setting - is used, more outstanding cleanup operations can be left undone - while a scheduler is idling. When an eager setting is used, - schedulers will more frequently be woken, potentially increasing - CPU-utilization. -

-

NOTE: This flag may be removed or changed at any time without prior notice. -

-
- +sws default|legacy - -

- Set scheduler wakeup strategy. Default strategy changed in erts-5.10/OTP-R16A. This strategy was previously known as proposal in OTP-R15. The legacy strategy was used as default from R13 up to and including R15. -

-

NOTE: This flag may be removed or changed at any time without prior notice. -

-
- +swt very_low|low|medium|high|very_high - -

Set scheduler wakeup threshold. Default is medium. - The threshold determines when to wake up sleeping schedulers - when more work than can be handled by currently awake schedulers - exist. A low threshold will cause earlier wakeups, and a high - threshold will cause later wakeups. Early wakeups will - distribute work over multiple schedulers faster, but work will - more easily bounce between schedulers. -

-

NOTE: This flag may be removed or changed at any time - without prior notice. -

-
- +spp Bool + + +swct very_eager|eager|medium|lazy|very_lazy -

Set default scheduler hint for port parallelism. If set to - true, the VM will schedule port tasks when doing so will - improve parallelism in the system. If set to false, the VM - will try to perform port tasks immediately, improving latency at the - expense of parallelism. If this flag has not been passed, the - default scheduler hint for port parallelism is currently - false. The default used can be inspected in runtime by - calling erlang:system_info(port_parallelism). - The default can be overriden on port creation by passing the - parallelism - option to open_port/2

. -
- - -

Suggested stack size, in kilowords, for scheduler threads. - Valid range is 4-8192 kilowords. The default stack size - is OS dependent.

-
+

Sets scheduler wake cleanup threshold. Defaults to medium. + Controls how eager schedulers are to be requesting + wakeup because of certain cleanup operations. When a lazy setting + is used, more outstanding cleanup operations can be left undone + while a scheduler is idling. When an eager setting is used, + schedulers are more frequently woken, potentially increasing + CPU-utilization.

+ +

This flag can be removed or changed at any time without prior + notice.

+
+ + +sws default|legacy + +

Sets scheduler wakeup strategy. Default strategy changed in + ERTS 5.10 (Erlang/OTP R16A). This strategy was known as + proposal in Erlang/OTP R15. The legacy strategy + was used as default from R13 up to and including R15.

+ +

This flag can be removed or changed at any time without prior + notice.

+
+
+ + +swt very_low|low|medium|high|very_high + +

Sets scheduler wakeup threshold. Defaults to medium. + The threshold determines when to wake up sleeping schedulers + when more work than can be handled by currently awake schedulers + exists. A low threshold causes earlier wakeups, and a high + threshold causes later wakeups. Early wakeups distribute work + over multiple schedulers faster, but work does more easily bounce + between schedulers.

+ +

This flag can be removed or changed at any time without prior + notice.

+
+
-

Set the maximum number of atoms the VM can handle. Default is 1048576.

+

Sets the maximum number of atoms the virtual machine can handle. + Defaults to 1,048,576.

-

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.

-

Currently, modified timing affects the following:

+

Enables modified timing and sets the modified timing level. Valid + range is 0-9. The timing of the runtime system is changed. A high + level usually means a greater change than a low level. Changing the + timing can be very useful for finding timing-related bugs.

+

Modified timing affects the following:

Process spawning - -

A process calling , , - , or 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.

+ A process calling , + , , + or is scheduled out immediately + after completing the call. When higher modified timing levels are + used, the caller also sleeps for a while after it is scheduled out. Context reductions - The amount of reductions a process is a allowed to - use before being scheduled out is increased or reduced. + The number of reductions a process is allowed to use before it + is scheduled out is increased or reduced. + Input reductions - The amount of reductions performed before checking I/O - is increased or reduced. + The number of reductions performed before checking I/O is + increased or reduced. +
-

NOTE: Performance will suffer when modified timing - is enabled. This flag is only intended for testing and - debugging. Also note that and - trace messages will be lost when tracing on the spawn BIFs. This - flag may be removed or changed at any time without prior notice.

-
- - -

Makes the emulator print out its version number.

+ +

Performance suffers when modified timing is enabled. This flag is + only intended for testing and debugging.

+

and + trace messages are lost when tracing on the spawn BIFs.

+

This flag can be removed or changed at any time without prior + notice.

+

Verbose.

+ + +

Makes the emulator print its version number.

+
-

Sets the mapping of warning messages for . - Messages sent to the error logger using one of the warning - routines can be mapped either to errors (), - warnings (), or info reports - (). The default is warnings. +

Sets the mapping of warning messages for + . Messages sent to the error logger + using one of the warning routines can be mapped to errors + (), warnings (), or + information reports (). Defaults to warnings. The current mapping can be retrieved using - . See - error_logger(3) - for further information.

+ . For more information, + see + error_logger:warning_map/0 in Kernel.

-

Miscellaneous flags.

+

Miscellaneous flags:

+zdbbl size -

Set the distribution buffer busy limit - (dist_buf_busy_limit) - in kilobytes. Valid range is 1-2097151. Default is 1024.

-

A larger buffer limit will allow processes to buffer - more outgoing messages over the distribution. When the - buffer limit has been reached, sending processes will be - suspended until the buffer size has shrunk. The buffer - limit is per distribution channel. A higher limit will - give lower latency and higher throughput at the expense - of higher memory usage.

+

Sets the distribution buffer busy limit + ( + dist_buf_busy_limit) + in kilobytes. Valid range is 1-2097151. Defaults to 1024.

+

A larger buffer limit allows processes to buffer + more outgoing messages over the distribution. When the + buffer limit has been reached, sending processes will be + suspended until the buffer size has shrunk. The buffer + limit is per distribution channel. A higher limit + gives lower latency and higher throughput at the expense + of higher memory use.

+zdntgc time -

Set the delayed node table garbage collection time - (delayed_node_table_gc) - in seconds. Valid values are either infinity or - an integer in the range [0-100000000]. Default is 60.

-

Node table entries that are not referred will linger - in the table for at least the amount of time that this - parameter determines. The lingering prevents repeated - deletions and insertions in the tables from occurring. -

+

Sets the delayed node table garbage collection time + ( + delayed_node_table_gc) + in seconds. Valid values are either infinity or + an integer in the range 0-100000000. Defaults to 60.

+

Node table entries that are not referred linger + in the table for at least the amount of time that this + parameter determines. The lingering prevents repeated + deletions and insertions in the tables from occurring.

@@ -1462,104 +1452,95 @@
- Environment variables + Environment Variables

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 in the current directory.

+ variable is the filename of the crash dump file. + If the variable is not set, the name of the crash dump file is + in the current directory.

-

Unix systems: 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.

+

Unix systems: If the emulator needs to write a crash dump, + it uses the value of this variable to set the nice value + for the process, thus lowering its priority. Valid range is + 1-39 (higher values are replaced with 39). The highest + value, 39, gives the process the lowest priority.

-

Unix systems: 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.

- -

If the environment variable is not set or it is set to zero seconds, , - the runtime system will not even attempt to write the crash dump file. It will just terminate. -

-

If the environment variable is set to negative valie, e.g. , - the runtime system will wait indefinitely for the crash dump file to be written. -

-

This environment variable is used in conjuction with - heart if heart is running: -

- - -

- Suppresses the writing a crash dump file entirely, - thus rebooting the runtime system immediately. - This is the same as not setting the environment variable. -

-
- -

Setting the environment variable to a negative value will cause the - termination of the runtime system to wait until the crash dump file - has been completly written. -

-
- -

- Will wait for S seconds to complete the crash dump file and - then terminate the runtime system. -

-
-
+

Unix systems: This variable gives the number of seconds + that the emulator is allowed to spend writing a crash dump. When the + given number of seconds have elapsed, the emulator is terminated by a + SIGALRM signal.

+

If the variable is not set or set to 0 seconds + (), the runtime system does + not even attempt to write the crash dump file. It only terminates.

+

If the variable is set to negative value, such as + , the runtime system + waits indefinitely for the crash dump file to be written.

+

This variable is used with + kernel:heart if heart is running:

+ + + Suppresses the writing a crash dump file entirely, thus + rebooting the runtime system immediately. This is the same as not + setting the environment variable. + + + Setting the environment variable to a negative value causes the + termination of the runtime system to wait until the crash dump file + has been completly written. + + + Waits for S seconds to complete the crash dump file and + then terminates the runtime system. + +
-

The content of this environment variable will be added to the - beginning of the command line for .

-

The flag is treated specially. Its scope ends - at the end of the environment variable content. Arguments - following an flag are moved on the command line into - the section, i.e. the end of the command line - following after an flag.

-
- and - -

The content of these environment variables will be added to the - end of the command line for .

-

The flag is treated specially. Its scope ends - at the end of the environment variable content. Arguments - following an flag are moved on the command line into - the section, i.e. the end of the command line - following after an flag.

+

The content of this variable is added to the beginning of the + command line for .

+

Flag is treated in a special way. Its + scope ends at the end of the environment variable content. Arguments + following an flag are moved on the command + line into section , that is, the end of the + command line following an flag.

+
+ and + + +

The content of these variables are added to the end of the command + line for .

+

Flag is treated in a special way. Its + scope ends at the end of the environment variable content. Arguments + following an flag are moved on the command + line into section , that is, the end of the + command line following an flag.

-

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 code(3).

+

Contains a list of additional library directories that the code + server searches for applications and adds to the code path; see + kernel:code(3).

-

This environment variable may be set to a comma-separated - list of IP addresses, in which case the - epmd daemon - will listen only on the specified address(es) and on the - loopback address (which is implicitly added to the list if it - has not been specified).

+

Can be set to a comma-separated list of IP addresses, in which case + the epmd daemon listens only + on the specified address(es) and on the loopback address (which is + implicitly added to the list if it has not been specified).

-

This environment variable can contain the port number to use when - communicating with epmd. The default - port will work fine in most cases. A different port can be specified +

Can contain the port number to use when communicating with + epmd. The default port works + fine in most cases. A different port can be specified to allow nodes of independent clusters to co-exist on the same host. - All nodes in a cluster must use the same epmd port number.

+ All nodes in a cluster must use the same epmd port number.

@@ -1567,59 +1548,64 @@
Configuration -

The standard Erlang/OTP system can be re-configured to change the default - behavior on start-up.

+

The standard Erlang/OTP system can be reconfigured to change the default + behavior on startup.

- The .erlang Start-up File - -

When Erlang/OTP is started, the system searches for a file named .erlang - in the directory where Erlang/OTP is started. If not found, the user's home - directory is searched for an .erlang file.

-

If an .erlang file is found, it is assumed to contain valid Erlang expressions. - These expressions are evaluated as if they were input to the shell.

-

A typical .erlang file contains a set of search paths, for example:

- -
- user_default and shell_default - -

Functions in the shell which are not prefixed by a module name are assumed - to be functional objects (Funs), built-in functions (BIFs), or belong to the - module user_default or shell_default.

-

To include private shell commands, define them in a module user_default and - add the following argument as the first line in the .erlang file.

+ The .erlang startup file + +

When Erlang/OTP is started, the system searches for a file named + .erlang in the directory where Erlang/OTP is started. If not + found, the user's home directory is searched for an .erlang + file.

+

If an .erlang file is found, it is assumed to contain valid + Erlang expressions. These expressions are evaluated as if they were + input to the shell.

+

A typical .erlang file contains a set of search paths, for + example:

-
- erl - -

If the contents of .erlang are changed and a private version of - user_default is defined, it is possible to customize the Erlang/OTP environment. - More powerful changes can be made by supplying command line arguments in the - start-up script erl. Refer to erl(1) and init(3) - for further information.

-
+io:format("executing user profile in HOME/.erlang\n",[]). +code:add_path("/home/calvin/test/ebin"). +code:add_path("/home/hobbes/bigappl-1.2/ebin"). +io:format(".erlang rc finished\n",[]). ]]> +
+ user_default and shell_default + +

Functions in the shell that are not prefixed by a module name are + assumed to be functional objects (funs), built-in functions (BIFs), + or belong to the module user_default or + shell_default.

+

To include private shell commands, define them in a module + user_default and add the following argument as the first line + in the .erlang file:

+ +
+ erl + +

If the contents of .erlang are changed and a private version + of user_default is defined, the Erlang/OTP environment can be + customized. More powerful changes can be made by supplying + command-line arguments in the startup script erl. For more + information, see init(3).

+
-
- SEE ALSO -

init(3), - erl_prim_loader(3), - erl_boot_server(3), - code(3), - application(3), - heart(3), - net_kernel(3), - auth(3), - make(3), - epmd(1), - erts_alloc(3)

+
+ See Also +

epmd(1), + erl_prim_loader(3), + erts_alloc(3), + init(3), + + kernel:application(3), + kernel:auth(3), + kernel:code(3), + + kernel:erl_boot_server(3), + kernel:heart(3), + kernel:net_kernel(3), + tools:make(3)

diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml index 25f601a235..f1979ac23f 100644 --- a/erts/doc/src/erl_dist_protocol.xml +++ b/erts/doc/src/erl_dist_protocol.xml @@ -32,1061 +32,989 @@ erl_dist_protocol.xml -

-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. -

- -

The distribution protocol can be divided into four (4) parts:

- - -

- 1. Low level socket connection. -

-
- - 2. Handshake, interchange node name and authenticate. - - - 3. Authentication (done by net_kernel). - - - 4. Connected. - -
-

- A node fetches the Port number of another node through the EPMD (at the - other host) in order to initiate a connection request. -

-

-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. -

-

-By default EPMD listens on port 4369. -

-

- 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). -

- -

The integers in all multi-byte fields are in big-endian order.

+

This description is far from complete. It will be updated if the + protocol is updated. However, the protocols, both from Erlang + nodes to the Erlang Port Mapper Daemon (EPMD) and between Erlang nodes + are stable since many years.

+ +

The distribution protocol can be divided into four parts:

+ + + +

Low-level socket connection (1)

+
+ +

Handshake, interchange node name, and authenticate (2)

+
+ +

Authentication (done by + kernel:net_kernel) (3)

+
+ +

Connected (4)

+
+
+ +

A node fetches the port number of another node through the EPMD (at the + other host) to initiate a connection request.

+ +

For each host, where a distributed Erlang node is running, also an EPMD + is to be running. The EPMD can be started explicitly or automatically + as a result of the Erlang node startup.

+ +

By default the EPMD listens on port 4369.

+ +

(3) and (4) above are performed at the same level but the net_kernel + disconnects the other node if it communicates using an invalid cookie (after + 1 second).

+ +

The integers in all multibyte fields are in big-endian order.

EPMD Protocol -

- The requests served by the EPMD (Erlang Port Mapper Daemon) are - summarized in the figure below. -

- - - - Summary of EPMD requests. - - -

- Each request *_REQ is preceded by a two-byte length field. - Thus, the overall request format is: -

+

The requests served by the EPMD are summarized in the following + figure.

+ + + Summary of EPMD Requests + + +

Each request *_REQ is preceded by a 2 byte length field. + Thus, the overall request format is as follows:

+ + + + 2 + n + + + Length + Request + + Request Format +
+ +
+ Register a Node in EPMD +

When a distributed node is started it registers itself in the EPMD. + The message ALIVE2_REQ described below is sent from the node to + the EPMD. The response from the EPMD is ALIVE2_RESP.

+ + + + 1 + 2 + 1 + 1 + 2 + 2 + 2 + Nlen + 2 + Elen + + + 120 + PortNo + NodeType + Protocol + HighestVersion + LowestVersion + Nlen + NodeName + Elen + Extra + + ALIVE2_REQ (120) +
+ + + PortNo + +

The port number on which the node accept connection requests.

+
+ NodeType + +

77 = normal Erlang node, 72 = hidden node (C-node), ...

+
+ Protocol + +

0 = TCP/IPv4, ...

+
+ HighestVersion + +

The highest distribution version that this node can handle. + The value in Erlang/OTP R6B and later is 5.

+
+ LowestVersion + +

The lowest distribution version that this node can handle. + The value in Erlang/OTP R6B and later is 5.

+
+ Nlen + +

The length (in bytes) of field NodeName.

+
+ NodeName + +

The node name as an UTF-8 encoded string of Nlen bytes.

+
+ Elen + +

The length of field Extra.

+
+ Extra + +

Extra field of Elen bytes.

+
+
+ +

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.

+ +

The response message ALIVE2_RESP is as follows:

+ + + + 1 + 1 + 2 + + + 121 + Result + Creation + + ALIVE2_RESP (121) +
+ +

Result = 0 -> ok, result > 0 -> error.

+
+ +
+ Unregister a Node from EPMD +

A node unregisters itself from the EPMD by closing the TCP + connection to EPMD established when the node was registered.

+
+ +
+ Get the Distribution Port of Another Node +

When one node wants to connect to another node it starts with + a PORT_PLEASE2_REQ request to the EPMD on the host where the + node resides to get the distribution port that the node listens to.

+ + + + 1 + N + + + 122 + NodeName + + PORT_PLEASE2_REQ (122) +
+ +

where N = Length - 1.

+ + + + 1 + 1 + + + 119 + Result + + PORT2_RESP (119) Response Indicating Error, Result > 0 + +
+ +

or

+ + + + 1 + 1 + 2 + 1 + 1 + 2 + 2 + 2 + Nlen + 2 + Elen + + + 119 + Result + PortNo + NodeType + Protocol + HighestVersion + LowestVersion + Nlen + NodeName + Elen + >Extra + + PORT2_RESP, Result = 0 +
+ +

If Result > 0, the packet only consists of + [119, Result].

+ +

The EPMD closes the socket when it has sent the information.

+
+ +
+ Get All Registered Names from EPMD +

This request is used through the Erlang function + + net_adm:names/1,2. A TCP connection is opened + to the EPMD and this request is sent.

+ + + + 1 + + + 110 + + NAMES_REQ (110) +
+ +

The response for a NAMES_REQ is as follows:

+ + + + 4 +   + + + EPMDPortNo + NodeInfo* + + NAMES_RESP +
+ +

NodeInfo is a string written for each active node. + When all NodeInfo has been written the connection is + closed by the EPMD.

+ +

NodeInfo is, as expressed in Erlang:

+ + +io:format("name ~ts at port ~p~n", [NodeName, Port]). +
+ +
+ Dump All Data from EPMD +

This request is not really used, it is to be regarded as a debug + feature.

+ + + + 1 + + + 100 + + DUMP_REQ +
+ +

The response for a DUMP_REQ is as follows:

+ + + + 4 +   + + + EPMDPortNo + NodeInfo* + + DUMP_RESP +
+ +

NodeInfo is a string written for each node kept in the EPMD. + When all NodeInfo has been written the connection is + closed by the EPMD.

+ +

NodeInfo is, as expressed in Erlang:

+ + +io:format("active name ~ts at port ~p, fd = ~p~n", + [NodeName, Port, Fd]). + +

or

+ + +io:format("old/unused name ~ts at port ~p, fd = ~p ~n", + [NodeName, Port, Fd]). +
+ +
+ Kill EPMD +

This request kills the running EPMD. It is almost never used.

+ + + + 1 + + + 107 + + KILL_REQ +
+ +

The response for a KILL_REQ is as follows:

- - 2 - n - - - Length - Request - -
- -
- Register a node in the EPMD -

- 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. -

- - - 1 - 2 - 1 - 1 - 2 - 2 - 2 - Nlen - 2 - Elen - - - 120 - PortNo - NodeType - Protocol - HighestVersion - LowestVersion - Nlen - NodeName - Elen - Extra - - ALIVE2_REQ (120)
- - PortNo - - The port number on which the node accept connection requests. - - NodeType - - 77 = normal Erlang node, 72 = hidden node (C-node),... - - Protocol - - 0 = tcp/ip-v4, ... - - HighestVersion - - The highest distribution version that this node can handle. - The value in R6B and later is 5. - - LowestVersion - - The lowest distribution version that this node can handle. - The value in R6B and later is 5. - - Nlen - - The length (in bytes) of the NodeName field. - - NodeName - - The NodeName as an UTF-8 encoded string of - Nlen bytes. - - Elen - - The length of the Extra field. - - Extra - - Extra field of Elen bytes. - - -

- 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. -

-

- The response message ALIVE2_RESP is described below. -

- - - - 1 - 1 - 2 - - - 121 - Result - Creation - - ALIVE2_RESP (121)
-

- Result = 0 -> ok, Result > 0 -> error -

-
- -
- Unregister a node from the EPMD -

- A node unregisters itself from the EPMD by simply closing the - TCP connection towards EPMD established when the node was registered. -

-
- -
- Get the distribution port of another node -

- 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. -

- - - - 1 - N - - - 122 - NodeName - - PORT_PLEASE2_REQ (122)
-

- where N = Length - 1 -

- -

-

+ + 2 + + + OKString + + KILL_RESP + + +

where OKString is "OK".

+
+ +
+ STOP_REQ (Not Used) + + + 1 + n + + + 115 + NodeName + + STOP_REQ +
+ +

where n = Length - 1.

+ +

The current implementation of Erlang does not care if the connection + to the EPMD is broken.

+ +

The response for a STOP_REQ is as follows:

+ - - 1 - 1 - - - 119 - Result - - - PORT2_RESP (119) response indicating error, Result > 0. - + + 7 + + + OKString + + STOP_RESP
-

Or

+ +

where OKString is "STOPPED".

+ +

A negative response can look as follows:

+ - - 1 - 1 - 2 - 1 - 1 - 2 - 2 - 2 - Nlen - 2 - Elen - - - 119 - Result - PortNo - NodeType - Protocol - HighestVersion - LowestVersion - Nlen - NodeName - Elen - Extra - - PORT2_RESP when Result = 0.
-

-If Result > 0, the packet only consists of [119, Result]. -

- -

EPMD will close the socket as soon as it has sent the information.

-
- -
- Get all registered names from EPMD -

- This request is used via the Erlang function - net_adm:names/1,2. A TCP connection is opened - towards EPMD and this request is sent. -

- - - 1 - - - 110 - - NAMES_REQ (110)
- - -

The response for a NAMES_REQ looks like this:

- - - 4 -   - - - EPMDPortNo - NodeInfo* - - NAMES_RESP
-

- NodeInfo is a string written for each active node. - When all NodeInfo has been written the connection is - closed by EPMD. -

-

- NodeInfo is, as expressed in Erlang: -

- - io:format("name ~ts at port ~p~n", [NodeName, Port]). - -
- - -
- Dump all data from EPMD -

- This request is not really used, it should be regarded as a debug - feature. -

- - - 1 - - - 100 - - DUMP_REQ
- -

The response for a DUMP_REQ looks like this:

- - - 4 -   - - - EPMDPortNo - NodeInfo* - - DUMP_RESP
-

- NodeInfo is a string written for each node kept in EPMD. - When all NodeInfo has been written the connection is - closed by EPMD. -

-

- NodeInfo is, as expressed in Erlang: -

- - io:format("active name ~ts at port ~p, fd = ~p~n", - [NodeName, Port, Fd]). - -

- or -

- - io:format("old/unused name ~ts at port ~p, fd = ~p ~n", - [NodeName, Port, Fd]). - - -
- -
- Kill the EPMD -

- This request will kill the running EPMD. It is almost never used. -

- - - 1 - - - 107 - - KILL_REQ
- -

The response fo a KILL_REQ looks like this:

- - - 2 - - - OKString - - KILL_RESP
-

- where OKString is "OK". -

-
- -
- STOP_REQ (Not Used) -

- - - 1 - n - - - 115 - NodeName - - STOP_REQ
-

- where n = Length - 1 -

-

- The current implementation of Erlang does not care if the connection - to the EPMD is broken. -

-

The response for a STOP_REQ looks like this.

- - - 7 - - - OKString - - STOP_RESP
-

- where OKString is "STOPPED". -

-

A negative response can look like this.

- - - 7 - - - NOKString - - STOP_NOTOK_RESP
-

- where NOKString is "NOEXIST". -

-
+ + 7 + + + NOKString + + STOP_NOTOK_RESP + + +

where NOKString is "NOEXIST".

+
+
+
+ + Distribution Handshake +

This section describes the distribution handshake protocol introduced + in Erlang/OTP R6. This description was previously located in + $ERL_TOP/lib/kernel/internal_doc/distribution_handshake.txt and + has more or less been copied and "formatted" here. It has been almost + unchanged since 1999, but the handshake has not changed much since then + either.

+ +
+ General +

The TCP/IP distribution uses a handshake that expects a + connection-based protocol, that is, the protocol does not include any + authentication after the handshake procedure.

+ +

This is not entirely safe, as it is vulnerable against takeover + attacks, but it is a tradeoff between fair safety and performance.

+ +

The cookies are never sent in cleartext and the handshake procedure + expects the client (called A) to be the first one to prove that + it can generate a sufficient digest. The digest is generated with the + MD5 message digest algorithm and the challenges are expected to be + random numbers.

+
+ +
+ Definitions +

A challenge is a 32-bit integer in big-endian order. Below the function + gen_challenge() returns a random 32-bit integer used as a + challenge.

+ +

A digest is a (16 bytes) MD5 hash of the challenge (as text) + concatenated with the cookie (as text). Below, the function + gen_digest(Challenge, Cookie) generates a digest as described + above.

+ +

An out_cookie is the cookie used in outgoing communication to a + certain node, so that A's out_cookie for B is to + correspond with B's in_cookie for A and conversely. + A's out_cookie for B and A's + in_cookie for B need not be the same. Below the + function out_cookie(Node) returns the current node's + out_cookie for Node.

+ +

An in_cookie is the cookie expected to be used by another node + when communicating with us, so that A's in_cookie for + B corresponds with B's out_cookie for A. + Below the function in_cookie(Node) returns the current node's + in_cookie for Node.

+ +

The cookies are text strings that can be viewed as passwords.

+ +

Every message in the handshake starts with a 16-bit big-endian integer, + which contains the message length (not counting the two initial bytes). + In Erlang this corresponds to option {packet, 2} in + kernel:gen_tcp. + Notice that after the handshake, the distribution switches to 4 byte + packet headers.

-
- Distribution Handshake -

- - This section describes the distribution handshake protocol - introduced in the OTP-R6 release of Erlang/OTP. This - description was previously located in - $ERL_TOP/lib/kernel/internal_doc/distribution_handshake.txt, - and has more or less been copied and "formatted" here. It has been - more or less unchanged since the year 1999, but the handshake - should not have changed much since then either. -

-
- General -

- The TCP/IP distribution uses a handshake which expects a - connection based protocol, i.e. the protocol does not include - any authentication after the handshake procedure. -

-

- This is not entirely safe, as it is vulnerable against takeover - attacks, but it is a tradeoff between fair safety and performance. -

-

- The cookies are never sent in cleartext and the handshake procedure - expects the client (called A) to be the first one to prove that it can - generate a sufficient digest. The digest is generated with the - MD5 message digest algorithm and the challenges are expected to be very - random numbers. -

-
-
- Definitions -

- A challenge is a 32 bit integer number in big endian order. Below the function - gen_challenge() returns a random 32 bit integer used as a challenge. -

-

- A digest is a (16 bytes) MD5 hash of the Challenge (as text) concatenated - with the cookie (as text). Below, the function gen_digest(Challenge, Cookie) - generates a digest as described above. -

-

- An out_cookie is the cookie used in outgoing communication to a certain node, - so that A's out_cookie for B should correspond with B's in_cookie for A and - the other way around. A's out_cookie for B and A's in_cookie for B need NOT - be the same. Below the function out_cookie(Node) returns the current - node's out_cookie for Node. -

-

- An in_cookie is the cookie expected to be used by another node when - communicating with us, so that A's in_cookie for B corresponds with B's - out_cookie for A. Below the function in_cookie(Node) returns the current - node's in_cookie for Node. -

-

- The cookies are text strings that can be viewed as passwords. -

-

- Every message in the handshake starts with a 16 bit big endian integer - which contains the length of the message (not counting the two initial bytes). - In erlang this corresponds to the gen_tcp option {packet, 2}. Note that after - the handshake, the distribution switches to 4 byte packet headers. -

- -
-
- The Handshake in Detail -

- Imagine two nodes, node A, which initiates the handshake and node B, which - accepts the connection. -

- - 1) connect/accept -

A connects to B via TCP/IP and B accepts the connection.

- 2) send_name/receive_name -

A sends an initial identification to B. B receives the message. - The message looks like this (every "square" being one byte and the packet - header removed): -

-
+
+    
+ The Handshake in Detail +

Imagine two nodes, A that initiates the handshake and B + that accepts the connection.

+ + + 1) connect/accept + +

A connects to B through TCP/IP and B accepts + the connection.

+
+ 2) send_name/receive_name + +

A sends an initial identification to B, which + receives the message. The message looks as follows (every "square" + is one byte and the packet header is removed):

+
 +---+--------+--------+-----+-----+-----+-----+-----+-----+-...-+-----+
 |'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Name0|Name1| ... |NameN|
-+---+--------+--------+-----+-----+-----+-----+-----+-----+-... +-----+
-
-

- The 'n' is just a message tag. - Version0 and Version1 is the distribution version selected by node A, - based on information from EPMD. (16 bit big endian) - Flag0 ... Flag3 are capability flags, the capabilities defined in - $ERL_TOP/lib/kernel/include/dist.hrl. - (32 bit big endian) - Name0 ... NameN is the full nodename of A, as a string of bytes (the - packet length denotes how long it is). -

- 3) recv_status/send_status -

B sends a status message to A, which indicates - if the connection is allowed. The following status codes are defined:

- - ok - The handshake will continue. - ok_simultaneous - The handshake will continue, but A is informed that B - has another ongoing connection attempt that will be - shut down (simultaneous connect where A's name is - greater than B's name, compared literally). - nok - The handshake will not continue, as B already has an ongoing handshake - which it itself has initiated. (simultaneous connect where B's name is - greater than A's). - not_allowed - The connection is disallowed for some (unspecified) security - reason. - alive - A connection to the node is already active, which either means - that node A is confused or that the TCP connection breakdown - of a previous node with this name has not yet reached node B. - See 3B below. - -

This is the format of the status message:

-
++---+--------+--------+-----+-----+-----+-----+-----+-----+-... +-----+
+

'n' is the message tag. 'Version0' and 'Version1' is the + distribution version selected by A, based on information + from the EPMD. (16-bit big-endian) 'Flag0' ... 'Flag3' are + capability flags, the capabilities are defined in + $ERL_TOP/lib/kernel/include/dist.hrl. (32-bit big-endian) + 'Name0' ... 'NameN' is the full node name of A, as a string + of bytes (the packet length denotes how long it is).

+
+ 3) recv_status/send_status + +

B sends a status message to A, which indicates if the + connection is allowed. The following status codes are defined:

+ + ok + +

The handshake will continue.

+
+ ok_simultaneous + +

The handshake will continue, but A is informed that + B has another ongoing connection attempt that will be + shut down (simultaneous connect where A's name is + greater than B's name, compared literally).

+
+ nok + +

The handshake will not continue, as B already has an + ongoing handshake, which it itself has initiated (simultaneous + connect where B's name is greater than A's).

+
+ not_allowed + +

The connection is disallowed for some (unspecified) security + reason.

+
+ alive + +

A connection to the node is already active, which either means + that node A is confused or that the TCP connection + breakdown of a previous node with this name has not yet reached + node B. See step 3B below.

+
+
+

The format of the status message is as follows:

+
 +---+-------+-------+-...-+-------+
 |'s'|Status0|Status1| ... |StatusN|
-+---+-------+-------+-...-+-------+
-
-

- 's' is the message tag Status0 ... StatusN is the status as a string (not terminated) -

-
- 3B) send_status/recv_status -

If status was 'alive', node A will answer with - another status message containing either 'true' which means that the - connection should continue (The old connection from this node is broken), or - 'false', which simply means that the connection should be closed, the - connection attempt was a mistake.

- 4) recv_challenge/send_challenge -

If the status was ok or ok_simultaneous, - The handshake continues with B sending A another message, the challenge. - The challenge contains the same type of information as the "name" message - initially sent from A to B, with the addition of a 32 bit challenge:

-
++---+-------+-------+-...-+-------+
+

's' is the message tag. 'Status0' ... 'StatusN' is the status as a + string (not terminated).

+
+ 3B) send_status/recv_status + +

If status was alive, node A answers with another + status message containing either true, which means that the + connection is to continue (the old connection from this node is + broken), or false, which means that the connection is to be + closed (the connection attempt was a mistake.

+
+ 4) recv_challenge/send_challenge + +

If the status was ok or ok_simultaneous, the + handshake continues with B sending A another message, + the challenge. The challenge contains the same type of information + as the "name" message initially sent from A to B, plus + a 32-bit challenge:

+
 +---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-...-+-----+
 |'n'|Version0|Version1|Flag0|Flag1|Flag2|Flag3|Chal0|Chal1|Chal2|Chal3|Name0|Name1| ... |NameN|
-+---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-... +-----+
-
-

- Where Chal0 ... Chal3 is the challenge as a 32 bit big endian integer - and the other fields are B's version, flags and full nodename. -

- 5) send_challenge_reply/recv_challenge_reply -

Now A has generated a digest and its own challenge. Those are - sent together in a package to B:

-
++---+--------+--------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-... +-----+
+

'Chal0' ... 'Chal3' is the challenge as a 32-bit big-endian integer + and the other fields are B's version, flags, and full node + name.

+
+ 5) send_challenge_reply/recv_challenge_reply + +

Now A has generated a digest and its own challenge. Those + are sent together in a package to B:

+
 +---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+
 |'r'|Chal0|Chal1|Chal2|Chal3|Dige0|Dige1|Dige2|Dige3| ... |Dige15|
-+---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+
-
-

- Where 'r' is the tag, Chal0 ... Chal3 is A's challenge for B to handle and - Dige0 ... Dige15 is the digest that A constructed from the challenge B sent - in the previous step. -

- 6) recv_challenge_ack/send_challenge_ack -

B checks that the digest received from A is correct and generates a - digest from the challenge received from A. The digest is then sent to A. The - message looks like this:

-
++---+-----+-----+-----+-----+-----+-----+-----+-----+-...-+------+
+

'r' is the tag. 'Chal0' ... 'Chal3' is A's challenge for + B to handle. 'Dige0' ... 'Dige15' is the digest that A + constructed from the challenge B sent in the previous + step.

+
+ 6) recv_challenge_ack/send_challenge_ack + +

B checks that the digest received from A is correct + and generates a digest from the challenge received from A. + The digest is then sent to A. The message is as follows:

+
 +---+-----+-----+-----+-----+-...-+------+
 |'a'|Dige0|Dige1|Dige2|Dige3| ... |Dige15|
-+---+-----+-----+-----+-----+-...-+------+
-
-

- Where 'a' is the tag and Dige0 ... Dige15 is the digest calculated by B - for A's challenge.

- 7) -

A checks the digest from B and the connection is up.

-
-
-
- Semigraphic View -
-A (initiator)						B (acceptor)
-
-TCP connect ----------------------------------------->	
-							TCP accept
-
-send_name   ----------------------------------------->
-							recv_name
-
-	    <----------------------------------------	send_status
++---+-----+-----+-----+-----+-...-+------+
+

'a' is the tag. 'Dige0' ... 'Dige15' is the digest calculated by + B for A's challenge.

+ + 7) check + +

A checks the digest from B and the connection is + up.

+
+ +
+ +
+ Semigraphic View +
+A (initiator)                                      B (acceptor)
+
+TCP connect ------------------------------------>
+                                                   TCP accept
+
+send_name -------------------------------------->
+                                                   recv_name
+
+<---------------------------------------------- send_status
 recv_status
 (if status was 'alive'
- send_status - - - - - - - - - - - - - - - - - - - ->
-							recv_status)
-							ChB = gen_challenge()
-		          (ChB)
-	    <----------------------------------------	send_challenge
+ send_status - - - - - - - - - - - - - - - - - ->
+                                                   recv_status)
+                                                   ChB = gen_challenge()
+                          (ChB)
+<---------------------------------------------- send_challenge
 recv_challenge
-
 ChA = gen_challenge(),
 OCA = out_cookie(B),
 DiA = gen_digest(ChB,OCA)
-			  (ChA, DiA)
-send_challenge_reply -------------------------------->
-							recv_challenge_reply
-							ICB = in_cookie(A),
-							check:
-							DiA == gen_digest
-								(ChB, ICB) ?
-							- if OK:
-	    						 OCB = out_cookie(A),
-							 DiB = gen_digest
-			(DiB)					(ChA, OCB)
-	    <-----------------------------------------	 send_challenge_ack
-recv_challenge_ack					 DONE
-ICA = in_cookie(B),                                     - else
-check:                                                   CLOSE
-DiB == gen_digest(ChA,ICA) ?
-- if OK
+                          (ChA, DiA)
+send_challenge_reply --------------------------->
+                                                   recv_challenge_reply
+                                                   ICB = in_cookie(A),
+                                                   check:
+                                                   DiA == gen_digest (ChB, ICB)?
+                                                   - if OK:
+                                                    OCB = out_cookie(A),
+                                                    DiB = gen_digest (ChA, OCB)
+                          (DiB)
+<----------------------------------------------- send_challenge_ack
+recv_challenge_ack                                  DONE
+ICA = in_cookie(B),                                - else:
+check:                                              CLOSE
+DiB == gen_digest(ChA,ICA)?
+- if OK:
  DONE
-- else
- CLOSE
-
-
- -
- The Currently Defined Distribution Flags -

- Currently (OTP-R16) the following capability flags are defined: -

-
-%% The node should be published and part of the global namespace
--define(DFLAG_PUBLISHED,1).
-
-%% The node implements an atom cache (obsolete)
--define(DFLAG_ATOM_CACHE,2).
-
-%% The node implements extended (3 * 32 bits) references. This is
-%% required today. If not present connection will be refused.
--define(DFLAG_EXTENDED_REFERENCES,4).
-
-%% The node implements distributed process monitoring.
--define(DFLAG_DIST_MONITOR,8).
-
-%% The node uses separate tag for fun's (lambdas) in the distribution protocol.
--define(DFLAG_FUN_TAGS,16#10).
-
-%% The node implements distributed named process monitoring.
--define(DFLAG_DIST_MONITOR_NAME,16#20).
-
-%% The (hidden) node implements atom cache (obsolete)
--define(DFLAG_HIDDEN_ATOM_CACHE,16#40).
-
-%% The node understand new fun-tags
--define(DFLAG_NEW_FUN_TAGS,16#80).
-
-%% The node is capable of handling extended pids and ports. This is
-%% required today. If not present connection will be refused.
--define(DFLAG_EXTENDED_PIDS_PORTS,16#100).
-
-%%
--define(DFLAG_EXPORT_PTR_TAG,16#200).
-
-%%
--define(DFLAG_BIT_BINARIES,16#400).
-
-%% The node understands new float format
--define(DFLAG_NEW_FLOATS,16#800).
-
-%%
--define(DFLAG_UNICODE_IO,16#1000).
-
-%% The node implements atom cache in distribution header.
--define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000).
-
-%% The node understand the SMALL_ATOM_EXT tag
--define(DFLAG_SMALL_ATOM_TAGS, 16#4000).
-
-%% The node understand UTF-8 encoded atoms
--define(DFLAG_UTF8_ATOMS, 16#10000).
-
-
-
-
- -
- - Protocol between connected nodes -

- As of erts version 5.7.2 the runtime system passes a distribution - flag in the handshake stage that enables the use of a - distribution - header on all messages passed. Messages passed between - nodes are in this case on the following format: -

- - - 4 - d - n - m - - - Length - DistributionHeader - ControlMessage - Message - -
-

- where: -

-

- Length is equal to d + n + m -

-

- ControlMessage is a tuple passed using the external format of - Erlang. -

-

- Message is the message sent to another node using the '!' - (in external format). Note that Message is only passed in - combination with a ControlMessage encoding a send ('!'). -

-

- Also note that the - version number is omitted from the terms that follow a - distribution header. -

-

- 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: -

- - - 4 - 1 - n - m - - - Length - Type - ControlMessage - Message - -
-

- where: -

-

- Length is equal to 1 + n + m -

-

- Type is: 112 (pass through) -

-

- ControlMessage is a tuple passed using the external format of - Erlang. -

-

- Message is the message sent to another node using the '!' - (in external format). Note that Message is only passed in - combination with a ControlMessage encoding a send ('!'). -

-

- The ControlMessage is a tuple, where the first element - indicates which distributed operation it encodes. -

- - LINK - -

- {1, FromPid, ToPid} -

-
- - SEND - -

- {2, Unused, ToPid} -

-

- Note followed by Message -

-

- Unused is kept for backward compatibility -

-
- - EXIT - -

- {3, FromPid, ToPid, Reason} -

-
- - UNLINK - -

- {4, FromPid, ToPid} -

-
- - NODE_LINK - -

- {5} -

-
- - REG_SEND - -

- {6, FromPid, Unused, ToName} -

-

- Note followed by Message -

-

- Unused is kept for backward compatibility -

-
- - GROUP_LEADER - -

- {7, FromPid, ToPid} -

-
- - EXIT2 - -

- {8, FromPid, ToPid, Reason} -

-
-
-
- - -
- New Ctrlmessages for distrvsn = 1 (OTP R4) - - SEND_TT - -

- {12, Unused, ToPid, TraceToken} -

-

- Note followed by Message -

-

- Unused is kept for backward compatibility -

-
- - EXIT_TT - -

- {13, FromPid, ToPid, TraceToken, Reason} -

-
- - REG_SEND_TT - -

- {16, FromPid, Unused, ToName, TraceToken} -

-

- Note followed by Message -

-

- Unused is kept for backward compatibility -

-
- - EXIT2_TT - -

- {18, FromPid, ToPid, TraceToken, Reason} -

-
-
-
- -
- New Ctrlmessages for distrvsn = 2 -

- distrvsn 2 was never used. -

-
- -
- New Ctrlmessages for distrvsn = 3 (OTP R5C) -

- None, but the version number was increased anyway. -

+- else: + CLOSE
- New Ctrlmessages for distrvsn = 4 (OTP R6) -

- These are only recognized by Erlang nodes, not by hidden nodes. -

+ + Distribution Flags +

The following capability flags are defined:

- MONITOR_P - -

- {19, FromPid, ToProc, Ref} - - FromPid = monitoring process - ToProc = monitored process pid or name (atom) -

-
- - DEMONITOR_P - -

- {20, FromPid, ToProc, Ref} - We include the FromPid just in case we want to trace this. - - FromPid = monitoring process - ToProc = monitored process pid or name (atom) -

-
- - MONITOR_P_EXIT - -

- {21, FromProc, ToPid, Ref, Reason} - - FromProc = monitored process pid or name (atom) - ToPid = monitoring process - Reason = exit reason for the monitored process -

-
+ -define(DFLAG_PUBLISHED,1). + +

The node is to be published and part of the global namespace.

+
+ -define(DFLAG_ATOM_CACHE,2). + +

The node implements an atom cache (obsolete).

+
+ -define(DFLAG_EXTENDED_REFERENCES,4). + +

The node implements extended (3 × 32 bits) references. This + is required today. If not present, the connection is refused.

+
+ -define(DFLAG_DIST_MONITOR,8). + +

The node implements distributed process monitoring.

+
+ -define(DFLAG_FUN_TAGS,16#10). + +

The node uses separate tag for funs (lambdas) in the distribution + protocol.

+
+ -define(DFLAG_DIST_MONITOR_NAME,16#20). + +

The node implements distributed named process monitoring.

+
+ -define(DFLAG_HIDDEN_ATOM_CACHE,16#40). + +

The (hidden) node implements atom cache (obsolete).

+
+ -define(DFLAG_NEW_FUN_TAGS,16#80). + +

The node understand new fun tags.

+
+ -define(DFLAG_EXTENDED_PIDS_PORTS,16#100). + +

The node can handle extended pids and ports. This is required + today. If not present, the connection is refused.

+
+ -define(DFLAG_EXPORT_PTR_TAG,16#200). + + + -define(DFLAG_BIT_BINARIES,16#400). + + + -define(DFLAG_NEW_FLOATS,16#800). + +

The node understands new float format.

+
+ -define(DFLAG_UNICODE_IO,16#1000). + + + -define(DFLAG_DIST_HDR_ATOM_CACHE,16#2000). + +

The node implements atom cache in distribution header.

+
+ -define(DFLAG_SMALL_ATOM_TAGS, 16#4000). + +

The node understand the SMALL_ATOM_EXT tag.

+
+ -define(DFLAG_UTF8_ATOMS, 16#10000). + +

The node understand UTF-8 encoded atoms.

+
- +
+ +
+ + Protocol between Connected Nodes +

As from ERTS 5.7.2 the runtime system passes a distribution flag + in the handshake stage that enables the use of a + distribution header + on all messages passed. Messages passed between nodes have in + this case the following format:

+ + + + 4 + d + n + m + + + Length + DistributionHeader + ControlMessage + Message + + Format of Messages Passed between Nodes (as from ERTS 5.7.2) + +
+ + + Length + +

Equal to d + n + m.

+
+ ControlMessage + +

A tuple passed using the external format of Erlang.

+
+ Message + +

The message sent to another node using the '!' (in external format). + Notice that Message is only passed in combination with a + ControlMessage encoding a send ('!').

+
+
+ +

Notice that the version + number is omitted from the terms that follow a distribution header + .

+ +

Nodes with an ERTS version earlier than 5.7.2 does not pass the + distribution flag that enables the distribution header. Messages passed + between nodes have in this case the following format:

+ + + + 4 + 1 + n + m + + + Length + Type + ControlMessage + Message + + Format of Messages Passed between Nodes (before ERTS 5.7.2) + +
+ + + Length + +

Equal to 1 + n + m.

+
+ Type + +

Equal to 112 (pass through).

+
+ ControlMessage + +

A tuple passed using the external format of Erlang.

+
+ Message + +

The message sent to another node using the '!' (in external format). + Notice that Message is only passed in combination with a + ControlMessage encoding a send ('!').

+
+
+ +

The ControlMessage is a tuple, where the first element indicates + which distributed operation it encodes:

+ + + LINK + +

{1, FromPid, ToPid}

+
+ SEND + +

{2, Unused, ToPid}

+

Followed by Message.

+

Unused is kept for backward compatibility.

+
+ EXIT + +

{3, FromPid, ToPid, Reason}

+
+ UNLINK + +

{4, FromPid, ToPid}

+
+ NODE_LINK + +

{5}

+
+ REG_SEND + +

{6, FromPid, Unused, ToName}

+

Followed by Message.

+

Unused is kept for backward compatibility.

+
+ GROUP_LEADER + +

{7, FromPid, ToPid}

+
+ EXIT2 + +

{8, FromPid, ToPid, Reason}

+
+
+
+ +
+ New Ctrlmessages for distrvsn = 1 (Erlang/OTP R4) + + SEND_TT + +

{12, Unused, ToPid, TraceToken}

+

Followed by Message.

+

Unused is kept for backward compatibility.

+
+ EXIT_TT + +

{13, FromPid, ToPid, TraceToken, Reason}

+
+ REG_SEND_TT + +

{16, FromPid, Unused, ToName, TraceToken}

+

Followed by Message.

+

Unused is kept for backward compatibility.

+
+ EXIT2_TT + +

{18, FromPid, ToPid, TraceToken, Reason}

+
+
+
+ +
+ New Ctrlmessages for distrvsn = 2 +

distrvsn 2 was never used.

+
+ +
+ New Ctrlmessages for distrvsn = 3 (Erlang/OTP R5C) +

None, but the version number was increased anyway.

+
+ +
+ New Ctrlmessages for distrvsn = 4 (Erlang/OTP R6) +

These are only recognized by Erlang nodes, not by hidden nodes.

+ + + MONITOR_P + +

{19, FromPid, ToProc, Ref}, where + FromPid = monitoring process and + ToProc = monitored process pid or name (atom)

+
+ DEMONITOR_P + +

{20, FromPid, ToProc, Ref}, where + FromPid = monitoring process and + ToProc = monitored process pid or name (atom)

+

We include FromPid just in case we want to trace this.

+
+ MONITOR_P_EXIT + +

{21, FromProc, ToPid, Ref, Reason}, where + FromProc = monitored process pid or name (atom), + ToPid = monitoring process, and + Reason = exit reason for the monitored process

+
+
+
+ diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index d8116d4650..69c3375858 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -21,7 +21,6 @@ limitations under the License. - erl_driver Jakob Cederlund Jakob Cederlund @@ -33,519 +32,546 @@ erl_driver.xml erl_driver - API functions for an Erlang driver + API functions for an Erlang driver.

An Erlang driver is a library containing a set of native driver - callback functions that the Erlang VM calls when certain - events occur. There may be multiple instances of a driver, each + callback functions that the Erlang Virtual Machine calls when certain + events occur. There can be multiple instances of a driver, each instance is associated with an Erlang port.

+ -

Use this functionality with extreme care!

+ +

Use this functionality with extreme care.

A driver callback is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can not provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the driver callback function doesn't behave well, - the whole VM will misbehave.

- -

A driver callback that crash will crash the whole VM.

-

An erroneously implemented driver callback might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the driver callback.

-

A driver callback that do lengthy - work before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.

+ native code of the VM. Execution is not made in a safe environment. + The VM cannot provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the driver callback function does not behave well, + the whole VM will misbehave.

+ + +

A driver callback that crash will crash the whole VM.

+
+ +

An erroneously implemented driver callback can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the driver callback.

+
+ +

A driver callback doing + lengthy work before + returning degrades responsiveness of the VM and can cause + miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage and bad + load balancing between schedulers. Strange behaviors that can + occur because of lengthy work can also vary between Erlang/OTP + releases.

+
-
-

As of erts version 5.5.3 the driver interface has been extended - (see extended marker). - The extended interface introduce + + +

As from ERTS 5.5.3 the driver interface has been extended + (see + extended marker). The extended interface introduces version management, - the possibility to pass capability flags - (see driver flags) - to the runtime system at driver initialization, and some new - driver API functions.

+ the possibility to pass capability flags (see + + driver_flags) to the runtime system at driver + initialization, and some new driver API functions.

+ -

As of erts version 5.9 old drivers have to be recompiled - and have to use the extended interface. They also have to be - adjusted to the - 64-bit capable driver interface. - -

+

As from ERTS 5.9 old drivers must be recompiled + and use the extended interface. They must also be adjusted to the + + 64-bit capable driver interface.

+

The driver calls back to the emulator, using the API functions declared in erl_driver.h. They are used for - outputting data from the driver, using timers, etc.

+ outputting data from the driver, using timers, and so on.

+

Each driver instance is associated with a port. Every port has a port owner process. Communication with the port is normally done through the port owner process. Most of the functions take the port handle as an argument. This identifies the driver - instance. Note that this port handle must be stored by the driver, + instance. Notice that this port handle must be stored by the driver, it is not given when the driver is called from the emulator (see - driver_entry).

+ + driver_entry).

+

Some of the functions take a parameter of type - ErlDrvBinary, a driver binary. It should be both + ErlDrvBinary, a driver binary. It is to be both allocated and freed by the caller. Using a binary directly avoids one extra copying of data.

+

Many of the output functions have a "header buffer", with hbuf and hlen 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 + the port. (Although in the latest Erlang versions there is + the binary syntax, which enables you to match on the beginning of a binary.) - -

+ +

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 + driver level locking will be used, that is, only one emulator thread will execute code in the driver at a time. If port level locking - is used, multiple emulator threads may execute code in the driver - at the same time. There will only be one thread at a time calling - driver call-backs corresponding to the same port, though. In order - to enable port level locking set the ERL_DRV_FLAG_USE_PORT_LOCKING + is used, multiple emulator threads can execute code in the driver + at the same time. Only one thread at a time will call + driver callbacks corresponding to the same port, though. + To enable port level locking, set the ERL_DRV_FLAG_USE_PORT_LOCKING driver flag in - the driver_entry - used by the driver. When port level locking is used it is the - responsibility of the driver writer to synchronize all accesses + the driver_entry + used by the driver. When port level locking is used, + the driver writer is responsible for synchronizing all accesses to data shared by the ports (driver instances).

+

Most drivers written before the runtime system with SMP - support existed will be able to run in the runtime system - with SMP support without being rewritten if driver + support existed can run in the runtime system + with SMP support, without being rewritten, if driver level locking is used.

+

It is assumed that drivers do not access other drivers. If - drivers should access each other they have to provide their own - mechanism for thread safe synchronization. Such "inter driver + drivers access each other, they must provide their own + mechanism for thread-safe synchronization. Such "inter-driver communication" is strongly discouraged.

+

Previously, in the runtime system without SMP support, - specific driver call-backs were always called from the same + specific driver callbacks were always called from the same thread. This is not 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 most drivers not be a problem, but it might. - Drivers that depend on all call-backs being called in the - same thread, have to be rewritten before being used + to driver callbacks can be made from different threads. For example, + two consecutive calls to exactly the same callback for exactly + the same port can be made from two different threads. This + is for most drivers not a problem, but it can be. + Drivers that depend on all callbacks that are called in the + same thread, must be rewritten before they are used in the runtime system with SMP support.

+

Regardless of locking scheme used, calls to driver - call-backs may be made from different threads.

+ callbacks can be made from different threads.

-

Most functions in this API are not thread-safe, i.e., - they may not be called from an arbitrary thread. Functions - that are not documented as thread-safe may only be called from - driver call-backs or function calls descending from a driver - call-back call. Note that driver call-backs may be called from + +

Most functions in this API are not thread-safe, that is, + they cannot be called from any thread. Functions + that are not documented as thread-safe can only be called from + driver callbacks or function calls descending from a driver + callback call. Notice that driver callbacks can be called from different threads. This, however, is not a problem for any - function in this API, since the emulator has control over + function in this API, as the emulator has control over these threads.

+ -

Functions not explicitly documented as thread safe are - not thread safe. Also note that some functions - are only thread safe when used in a runtime +

Functions not explicitly documented as thread-safe are + not thread safe. Also notice that some functions + are only thread-safe when used in a runtime system with SMP support.

-

A function not explicitly documented as thread safe may at - some point in time have a thread safe implementation in the - runtime system. Such an implementation may however change to - a thread unsafe implementation at any time without - any notice at all. -

-

Only use functions explicitly documented as thread safe - from arbitrary threads.

+

A function not explicitly documented as thread-safe can, at + some point in time, have a thread-safe implementation in the + runtime system. Such an implementation can however change to + a thread unsafe implementation at any time without + any notice.

+

Only use functions explicitly documented as thread-safe + from arbitrary threads.

-

- As mentioned in the warning text at - the beginning of this document it is of vital importance that a driver callback - does return relatively fast. It is hard to give an exact maximum amount - of time that a driver callback is allowed to work, but as a rule of thumb - a well behaving driver callback should return before a millisecond has - passed. This can be achieved using different approaches. - If you have full control over the code that are to execute in the driver - callback, the best approach is to divide the work into multiple chunks of - work and trigger multiple calls to the - timeout callback using - zero timeouts. The - erl_drv_consume_timeslice() - function can be useful in order to determine when to trigger such - timeout callback calls. It might, however, not always be possible to - implement it this way, e.g. when calling third party libraries. In this - case you typically want to dispatch the work to another thread. - Information about thread primitives can be found below.

+ +

+ As mentioned in the warning text at + the beginning of this section, it is of vital importance that a driver + callback returns relatively fast. It is difficult to give an exact + maximum amount of time that a driver callback is allowed to work, but + usually a well-behaving driver callback is to return within 1 millisecond. + This can be achieved using different approaches. + If you have full control over the code to execute in the driver + callback, the best approach is to divide the work into multiple chunks of + work, and trigger multiple calls to the + time-out callback using + zero time-outs. Function + erl_drv_consume_timeslice can be useful to + determine when to trigger such time-out callback calls. However, sometimes + it cannot be implemented this way, for example when calling + third-party libraries. In this case, you typically want to dispatch the + work to another thread. Information about thread primitives is provided + below.

- FUNCTIONALITY + Functionality

All functions that a driver needs to do with Erlang are - performed through driver API functions. There are functions + performed through driver API functions. Functions exist for the following functionality:

+ Timer functions - Timer functions are used to control the timer that a driver - may use. The timer will have the emulator call the - timeout entry - function after a specified time. Only one timer is available - for each driver instance. + +

Control the timer that a driver can use. The timer has the + emulator call the + timeout entry function after a specified time. + Only one timer is available for each driver instance.

+
Queue handling

Every driver instance has an associated queue. This queue is a - SysIOVec that works as a buffer. It's mostly used for - the driver to buffer data that should be written to a device, + SysIOVec, which works as a buffer. It is mostly used for + the driver to buffer data that is to be written to a device, it is a byte stream. If the port owner process closes the - driver, and the queue is not empty, the driver will not be + driver, and the queue is not empty, the driver is not closed. This enables the driver to flush its buffers before closing.

-

The queue can be manipulated from arbitrary threads if - a port data lock is used. See documentation of the - ErlDrvPDL type for - more information.

+

The queue can be manipulated from any threads if + a port data lock is used. For more information, see + ErlDrvPDL.

Output functions - With the output functions, the driver sends data back to - the emulator. They will be received as messages by the port owner - process, see open_port/2. The vector function and the - function taking a driver binary are faster, because they avoid - copying the data buffer. There is also a fast way of sending - terms from the driver, without going through the binary term - format. + +

With these functions, the driver sends data back to the emulator. + The data is received as messages by the port owner process, see + + erlang:open_port/2. The vector function and the + function taking a driver binary are faster, as they avoid + copying the data buffer. There is also a fast way of sending + terms from the driver, without going through the binary term + format.

Failure - The driver can exit and signal errors up to Erlang. This is - only for severe errors, when the driver can't possibly keep - open. + +

The driver can exit and signal errors up to Erlang. This is + only for severe errors, when the driver cannot possibly keep + open.

+
Asynchronous calls - 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. + +

Erlang/OTP R7B and later versions have provision for + asynchronous function calls, using a thread pool provided by + Erlang. There is also a select call, which can be used for + asynchronous drivers.

+
Multi-threading -

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: -

- - Threads - Mutexes - Condition variables - Read/Write locks - Thread specific data - -

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. -

-

The Erlang driver thread API only returns error codes when it is - reasonable to recover from an error condition. If it isn't reasonable - to recover from an error condition, the whole runtime system is - terminated. For example, if a create mutex operation fails, an error - code is returned, but if a lock operation on a mutex fails, the - whole runtime system is terminated. -

-

Note that there exists no "condition variable wait with timeout" in - the Erlang driver thread API. This is due to issues with - pthread_cond_timedwait(). 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. -

-

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 - driver_system_info(). - 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 - driver_system_info(). - Also note that a lot of functions in the Erlang driver API are - not thread-safe regardless of whether SMP support is - enabled or not. If a function isn't documented as thread-safe it - is not thread-safe. -

-

NOTE: When executing in an emulator thread, it is - very important that you unlock all locks you - have locked before letting the thread out of your control; - otherwise, you are very likely 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. -

-

In the future there will probably be debug functionality - integrated with the Erlang driver thread API. All functions - that create entities take a name argument. Currently - the name 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. -

+

A POSIX thread like API for multi-threading is provided. The + Erlang driver thread API only provides a subset of the functionality + provided by the POSIX thread API. The subset provided is + more or less the basic functionality needed for multi-threaded + programming:

+ + Threads + Mutexes + + Condition variables + + Read/write locks + + Thread-specific data + +

The Erlang driver thread API can be used in conjunction with + the POSIX thread API on UN-ices and with the Windows native thread + API on Windows. The Erlang driver thread API has the advantage of + being portable, but there can exist situations where you want to + use functionality from the POSIX thread API or the Windows + native thread API.

+

The Erlang driver thread API only returns error codes when it is + reasonable to recover from an error condition. If it is not reasonable + to recover from an error condition, the whole runtime system is + terminated. For example, if a create mutex operation fails, an error + code is returned, but if a lock operation on a mutex fails, the + whole runtime system is terminated.

+

Notice that there is no "condition variable wait with time-out" in + the Erlang driver thread API. This because of issues with + pthread_cond_timedwait. When the system clock suddenly + is changed, it is not always guaranteed that you will wake up from + the call as expected. An Erlang runtime system must be able to + cope with sudden changes of the system clock. Therefore, we have + omitted it from the Erlang driver thread API. In the Erlang driver + case, time-outs can and are to be handled with the timer functionality + of the Erlang driver API.

+

In order for the Erlang driver thread API to function, thread + support must be enabled in the runtime system. An Erlang driver + can check if thread support is enabled by use of + + driver_system_info. + Notice that some functions in the Erlang driver API are thread-safe + only when the runtime system has SMP support, also this + information can be retrieved through + + driver_system_info. + Also notice that many functions in the Erlang driver API are + not thread-safe, regardless of whether SMP support is + enabled or not. If a function is not documented as thread-safe, it + is not thread-safe.

+ +

When executing in an emulator thread, it is + very important that you unlock all locks you + have locked before letting the thread out of your control; + otherwise you are very likely 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.

+
+

In the future, debug functionality will probably be + integrated with the Erlang driver thread API. All functions + that create entities take a name argument. Currently + the name argument is unused, but it will be used when + the debug functionality is implemented. If you name all + entities created well, the debug functionality will be able + to give you better error reports.

+
+ Adding/removing drivers + +

A driver can add and later remove drivers.

- Adding / removing drivers -

A driver can add and later remove drivers.

Monitoring processes -

A driver can monitor a process that does not own a port.

+ +

A driver can monitor a process that does not own a port.

+
Version management

Version management is enabled for drivers that have set the - extended_marker - field of their - driver_entry - to ERL_DRV_EXTENDED_MARKER. erl_driver.h defines - ERL_DRV_EXTENDED_MARKER, - ERL_DRV_EXTENDED_MAJOR_VERSION, and - ERL_DRV_EXTENDED_MINOR_VERSION. - ERL_DRV_EXTENDED_MAJOR_VERSION will be incremented when - driver incompatible changes are made to the Erlang runtime - system. Normally it will suffice to recompile drivers when the - ERL_DRV_EXTENDED_MAJOR_VERSION has changed, but it - could, under rare circumstances, mean that drivers have to - be slightly modified. If so, this will of course be documented. - ERL_DRV_EXTENDED_MINOR_VERSION will be incremented when - new features are added. The runtime system uses the minor version - of the driver to determine what features to use. - The runtime system will normally refuse to load a driver if the major + + extended_marker field of their + driver_entry + to ERL_DRV_EXTENDED_MARKER. erl_driver.h defines:

+ + +

ERL_DRV_EXTENDED_MARKER

+
+ +

ERL_DRV_EXTENDED_MAJOR_VERSION, which is incremented when + driver incompatible changes are made to the Erlang runtime + system. Normally it suffices to recompile drivers when + ERL_DRV_EXTENDED_MAJOR_VERSION has changed, but it + can, under rare circumstances, mean that drivers must + be slightly modified. If so, this will of course be + documented.

+
+ +

ERL_DRV_EXTENDED_MINOR_VERSION, which is incremented when + new features are added. The runtime system uses the minor version + of the driver to determine what features to use.

+
+
+

The runtime system normally refuses to load a driver if the major versions differ, or if the major versions are equal and the minor version used by the driver is greater than the one used by the runtime system. Old drivers with lower major versions - will however be allowed after a bump of the major version during - a transition period of two major releases. Such old drivers might - however fail if deprecated features are used.

-

The emulator will refuse to load a driver that does not use - the extended driver interface, - to allow for 64-bit capable drivers, - since incompatible type changes for the callbacks - output, - control and - call - were introduced in release R15B. A driver written - with the old types would compile with warnings and when - called return garbage sizes to the emulator causing it - to read random memory and create huge incorrect result blobs.

-

Therefore it is not enough to just recompile drivers written with - version management for pre-R15B types; the types have to be changed - in the driver suggesting other rewrites especially regarding - size variables. Investigate all warnings when recompiling!

-

Also, the API driver functions driver_output*, - driver_vec_to_buf, driver_alloc/realloc* - and the driver_* queue functions were changed to have - larger length arguments and return values. This is a - lesser problem since code that passes smaller types - will get them auto converted in the calls and as long as - the driver does not handle sizes that overflow an int - all will work as before.

+ are however allowed after a bump of the major version during + a transition period of two major releases. Such old drivers can, + however, fail if deprecated features are used.

+

The emulator refuses to load a driver that does not use + the extended driver interface, to allow for 64-bit capable drivers, + as incompatible type changes for the callbacks + output, + control, and + call + were introduced in Erlang/OTP R15B. A driver written + with the old types would compile with warnings and when + called return garbage sizes to the emulator, causing it + to read random memory and create huge incorrect result blobs.

+

Therefore it is not enough to only recompile drivers written with + version management for pre R15B types; the types must be changed + in the driver suggesting other rewrites, especially regarding size + variables. Investigate all warnings when recompiling.

+

Also, the API driver functions driver_output* and + driver_vec_to_buf, driver_alloc/realloc*, and the + driver_* queue functions were changed to have + larger length arguments and return values. This is a + lesser problem, as code that passes smaller types + gets them auto-converted in the calls, and as long as + the driver does not handle sizes that overflow an int, + all will work as before.

- Time Measurement -

Support for time measurement in drivers:

- - ErlDrvTime - ErlDrvTimeUnit - erl_drv_monotonic_time() - erl_drv_time_offset() - erl_drv_convert_time_unit() - + Time measurement + +

Support for time measurement in drivers:

+ + + ErlDrvTime + + ErlDrvTimeUnit + + erl_drv_monotonic_time + + erl_drv_time_offset + + erl_drv_convert_time_unit +
- - REWRITES FOR 64-BIT DRIVER INTERFACE - -

- For erts-5.9 two new integer types - ErlDrvSizeT and - ErlDrvSSizeT - were introduced that can hold 64-bit sizes if necessary. -

-

- To not update a driver and just recompile it probably works + Rewrites for 64-Bit Driver Interface +

ERTS 5.9 introduced two new integer types, + ErlDrvSizeT and + ErlDrvSSizeT, + which can hold 64-bit sizes if necessary.

+ +

To not update a driver and only recompile, it probably works when building for a 32-bit machine creating a false sense of security. Hopefully that will generate many important warnings. - But when recompiling the same driver later on for a 64-bit machine + But when recompiling the same driver later on for a 64-bit machine, there will be warnings and almost certainly crashes. - So it is a BAD idea to postpone updating the driver and - not fixing the warnings! -

-

- When recompiling with gcc use the -Wstrict-prototypes - flag to get better warnings. Try to find a similar flag if you - are using some other compiler. -

-

- Here follows a checklist for rewriting a pre erts-5.9 driver, - most important first. -

+ So it is a bad idea to postpone updating the driver and + not fixing the warnings.

+ +

When recompiling with gcc, use flag -Wstrict-prototypes + to get better warnings. Try to find a similar flag if you use + another compiler.

+ +

The following is a checklist for rewriting a pre ERTS 5.9 driver, + most important first:

+ Return types for driver callbacks -

- Rewrite driver callback +

Rrewrite driver callback control - to use return type ErlDrvSSizeT instead of int. -

-

- Rewrite driver callback + to use return type ErlDrvSSizeT instead of int.

+

Rewrite driver callback call - to use return type ErlDrvSSizeT instead of int. -

+ to use return type ErlDrvSSizeT instead of int.

-

- These changes are essential to not crash the emulator +

These changes are essential not to crash the emulator or worse cause malfunction. - Without them a driver may return garbage in the high 32 bits - to the emulator causing it to build a huge result from random - bytes either crashing on memory allocation or succeeding with - a random result from the driver call. -

+ Without them a driver can return garbage in the high 32 bits + to the emulator, causing it to build a huge result from random + bytes, either crashing on memory allocation or succeeding with + a random result from the driver call.

Arguments to driver callbacks -

- Driver callback +

Driver callback output now gets ErlDrvSizeT as 3rd argument instead - of previously int. -

-

- Driver callback + of previously int.

+

Driver callback control now gets ErlDrvSizeT as 4th and 6th arguments instead - of previously int. -

-

- Driver callback + of previously int.

+

Driver callback call now gets ErlDrvSizeT as 4th and 6th arguments instead - of previously int. -

-

- Sane compiler's calling conventions probably make these changes + of previously int.

+

Sane compiler's calling conventions probably make these changes necessary only for a driver to handle data chunks that require - 64-bit size fields (mostly larger than 2 GB since that is what + 64-bit size fields (mostly larger than 2 GB, as that is what an int of 32 bits can hold). But it is possible to think of non-sane calling conventions that would make the driver - callbacks mix up the arguments causing malfunction. -

+ callbacks mix up the arguments causing malfunction.

-

- The argument type change is from signed to unsigned which - may cause problems for e.g. loop termination conditions or - error conditions if you just change the types all over the place. -

+

The argument type change is from signed to unsigned. This + can cause problems for, for example, loop termination conditions or + error conditions if you only change the types all over the place. +

Larger size field in ErlIOVec -

- The size field in +

The size field in ErlIOVec has been changed to ErlDrvSizeT from int. - Check all code that use that field. -

-

- Automatic type casting probably makes these changes necessary only - for a driver that encounters sizes larger than 32 bits. -

+ Check all code that use that field.

+

Automatic type-casting probably makes these changes necessary only + for a driver that encounters sizes > 32 bits.

-

- The size field changed from signed to unsigned which - may cause problems for e.g. loop termination conditions or - error conditions if you just change the types all over the place. -

+

The size field changed from signed to unsigned. This + can cause problems for, for example, loop termination conditions or + error conditions if you only change the types all over the place. +

Arguments and return values in the driver API -

- Many driver API functions have changed argument type +

Many driver API functions have changed argument type and/or return value to ErlDrvSizeT from mostly int. - Automatic type casting probably makes these changes necessary only - for a driver that encounters sizes larger than 32 bits. -

+ Automatic type-casting probably makes these changes necessary only + for a driver that encounters sizes > 32 bits.

- driver_output + + driver_output 3rd argument - driver_output2 + + driver_output2 3rd and 5th arguments - - driver_output_binary - - 3rd 5th and 6th arguments - driver_outputv + + driver_output_binary + 3rd, 5th, and 6th arguments + + driver_outputv 3rd and 5th arguments - - driver_vec_to_buf - + + driver_vec_to_buf 3rd argument and return value - driver_alloc + + driver_alloc 1st argument - driver_realloc + + driver_realloc 2nd argument - - driver_alloc_binary - + + driver_alloc_binary 1st argument - - driver_realloc_binary - + + driver_realloc_binary 2nd argument - driver_enq + + driver_enq 3rd argument - driver_pushq + + driver_pushq 3rd argument - driver_deq + + driver_deq 2nd argument and return value - driver_sizeq - return value - driver_enq_bin - 3rd and 4th argument - driver_pushq_bin - 3rd and 4th argument - driver_enqv + + driver_sizeq + Return value + + driver_enq_bin + 3rd and 4th arguments + + driver_pushq_bin + 3rd and 4th arguments + + driver_enqv 3rd argument - driver_pushqv + + driver_pushqv 3rd argument - driver_peekqv - return value + + driver_peekqv + Return value -

- This is a change from signed to unsigned which - may cause problems for e.g. loop termination conditions and - error conditions if you just change the types all over the place. -

+

This is a change from signed to unsigned. This can cause + problems for, for example, loop termination conditions and error + conditions if you only change the types all over the place.

- DATA TYPES - + Data Types - ErlDrvSizeT -

An unsigned integer type to be used as size_t

- ErlDrvSSizeT -

A signed integer type the size of ErlDrvSizeT

- ErlDrvSysInfo + ErlDrvSizeT + +

An unsigned integer type to be used as size_t.

+
+ ErlDrvSSizeT -

- +

A signed integer type, the size of ErlDrvSizeT.

+
+ ErlDrvSysInfo + + typedef struct ErlDrvSysInfo { int driver_major_version; int driver_minor_version; @@ -558,390 +584,422 @@ typedef struct ErlDrvSysInfo { int nif_major_version; int nif_minor_version; int dirty_scheduler_support; -} ErlDrvSysInfo; - - -

- The ErlDrvSysInfo structure is used for storage of - information about the Erlang runtime system. - driver_system_info() - will write the system information when passed a reference to - a ErlDrvSysInfo structure. A description of the - fields in the structure follows: -

- - driver_major_version - The value of - ERL_DRV_EXTENDED_MAJOR_VERSION - when the runtime system was compiled. This value is the same - as the value of - ERL_DRV_EXTENDED_MAJOR_VERSION - used when compiling the driver; otherwise, the runtime system - would have refused to load the driver. - - driver_minor_version - The value of - ERL_DRV_EXTENDED_MINOR_VERSION - when the runtime system was compiled. This value might differ - from the value of - ERL_DRV_EXTENDED_MINOR_VERSION - used when compiling the driver. - - erts_version - A string containing the version number of the runtime system - (the same as returned by - erlang:system_info(version)). - - otp_release - A string containing the OTP release number - (the same as returned by - erlang:system_info(otp_release)). - - thread_support - A value != 0 if the runtime system has thread support; - otherwise, 0. - - smp_support - A value != 0 if the runtime system has SMP support; - otherwise, 0. - - async_threads - The number of async threads in the async thread pool used - by driver_async() - (the same as returned by - erlang:system_info(thread_pool_size)). - - scheduler_threads - The number of scheduler threads used by the runtime system - (the same as returned by - erlang:system_info(schedulers)). - - nif_major_version - The value of ERL_NIF_MAJOR_VERSION when the runtime system was compiled. - - nif_minor_version - The value of ERL_NIF_MINOR_VERSION when the runtime system was compiled. - - dirty_scheduler_support - A value != 0 if the runtime system has support for dirty scheduler threads; - otherwise 0. - +} ErlDrvSysInfo;
+

The ErlDrvSysInfo structure is used for storage of + information about the Erlang runtime system. + + driver_system_info + writes the system information when passed a reference to + a ErlDrvSysInfo structure. The fields in the structure + are as follows:

+ + driver_major_version + +

The value of + ERL_DRV_EXTENDED_MAJOR_VERSION + when the runtime system was compiled. This value is the same + as the value of + ERL_DRV_EXTENDED_MAJOR_VERSION + used when compiling the driver; otherwise the runtime system + would have refused to load the driver.

+
+ driver_minor_version + +

The value of + ERL_DRV_EXTENDED_MINOR_VERSION + when the runtime system was compiled. This value can differ + from the value of + ERL_DRV_EXTENDED_MINOR_VERSION + used when compiling the driver.

+
+ erts_version + +

A string containing the version number of the runtime system + (the same as returned by + + erlang:system_info(version)).

+
+ otp_release + +

A string containing the OTP release number + (the same as returned by + + erlang:system_info(otp_release)).

+
+ thread_support + +

A value != 0 if the runtime system has thread support; + otherwise 0.

+
+ smp_support + +

A value != 0 if the runtime system has SMP support; + otherwise 0.

+
+ async_threads + +

The number of async threads in the async thread pool used by + driver_async + (the same as returned by + + erlang:system_info(thread_pool_size)).

+
+ scheduler_threads + +

The number of scheduler threads used by the runtime system + (the same as returned by + + erlang:system_info(schedulers)).

+
+ nif_major_version + +

The value of ERL_NIF_MAJOR_VERSION when the runtime + system was compiled.

+
+ nif_minor_version + +

The value of ERL_NIF_MINOR_VERSION when the runtime + system was compiled.

+
+ dirty_scheduler_support + +

A value != 0 if the runtime system has support for dirty + scheduler threads; otherwise 0.

+
- ErlDrvBinary + ErlDrvBinary -

- + typedef struct ErlDrvBinary { ErlDrvSint orig_size; char orig_bytes[]; -} ErlDrvBinary; - +} ErlDrvBinary;

The ErlDrvBinary structure is a binary, as sent between the emulator and the driver. All binaries are reference counted; when driver_binary_free is called, the reference count is decremented, when it reaches zero, - the binary is deallocated. The orig_size is the size - of the binary, and orig_bytes is the buffer. The - ErlDrvBinary does not have a fixed size, its size is + the binary is deallocated. orig_size is the binary size + and orig_bytes is the buffer. + ErlDrvBinary has not a fixed size, its size is orig_size + 2 * sizeof(int).

The refc field has been removed. The reference count of an ErlDrvBinary is now stored elsewhere. The - reference count of an ErlDrvBinary can be accessed via - driver_binary_get_refc(), - driver_binary_inc_refc(), - and - driver_binary_dec_refc().

+ reference count of an ErlDrvBinary can be accessed through + + driver_binary_get_refc, + + driver_binary_inc_refc, and + + driver_binary_dec_refc.

Some driver calls, such as driver_enq_binary, increment the driver reference count, and others, such as driver_deq decrement it.

-

Using a driver binary instead of a normal buffer, is often - faster, since the emulator doesn't need to copy the data, +

Using a driver binary instead of a normal buffer is often + faster, as the emulator needs not to copy the data, only the pointer is used.

A driver binary allocated in the driver, with - driver_alloc_binary, should be freed in the driver (unless otherwise stated), - with driver_free_binary. (Note that this doesn't + driver_alloc_binary, is to be freed in the driver + (unless otherwise stated) + with driver_free_binary. (Notice that this does not necessarily deallocate it, if the driver is still referred in the emulator, the ref-count will not go to zero.)

Driver binaries are used in the driver_output2 and driver_outputv calls, and in the queue. Also the - driver call-back outputv uses driver - binaries.

-

If the driver for some reason or another, wants to keep a - driver binary around, in a static variable for instance, the - reference count should be incremented, - and the binary can later be freed in the stop call-back, with - driver_free_binary.

-

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.

-

Since erts version 5.5 (OTP release R11B), orig_bytes is + driver callback + outputv uses driver binaries.

+

If the driver for some reason wants to keep a + driver binary around, for example in a static variable, the + reference count is to be incremented, and the binary can later + be freed in the + stop callback, with driver_free_binary.

+

Notice that as a driver binary is shared by the driver and + the emulator. A binary received from the emulator or sent to + the emulator must not be changed by the driver.

+

Since ERTS 5.5 (Erlang/OTP R11B), orig_bytes is guaranteed to be properly aligned for storage of an array of doubles (usually 8-byte aligned).

- ErlDrvData + ErlDrvData -

The ErlDrvData is a handle to driver-specific data, - passed to the driver call-backs. It is a pointer, and is +

A handle to driver-specific data, + passed to the driver callbacks. It is a pointer, and is most often type cast to a specific pointer in the driver.

- SysIOVec + SysIOVec -

This is a system I/O vector, as used by writev on - unix and WSASend on Win32. It is used in +

A system I/O vector, as used by writev on + Unix and WSASend on Win32. It is used in ErlIOVec.

- ErlIOVec + ErlIOVec -

- + typedef struct ErlIOVec { int vsize; ErlDrvSizeT size; SysIOVec* iov; ErlDrvBinary** binv; -} ErlIOVec; - -

The I/O vector used by the emulator and drivers, is a list +} ErlIOVec; +

The I/O vector used by the emulator and drivers is a list of binaries, with a SysIOVec pointing to the buffers of the binaries. It is used in driver_outputv and the - outputv - driver call-back. Also, the driver queue is an + outputv + driver callback. Also, the driver queue is an ErlIOVec.

- - ErlDrvMonitor + ErlDrvMonitor

When a driver creates a monitor for a process, a ErlDrvMonitor 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).

-

The driver writer should provide the memory for storing the - monitor when calling driver_monitor_process. The + data type that can be assigned to, but not compared without + using the supplied compare function (that is, it behaves like + a struct).

+

The driver writer is to provide the memory for storing the + monitor when calling + driver_monitor_process. The address of the data is not stored outside of the driver, so - the ErlDrvMonitor can be used as any other datum, it - can be copied, moved in memory, forgotten etc.

+ ErlDrvMonitor can be used as any other data, it + can be copied, moved in memory, forgotten, and so on.

- ErlDrvNowData + ErlDrvNowData -

The ErlDrvNowData structure holds a timestamp +

The ErlDrvNowData structure holds a time stamp consisting of three values measured from some arbitrary point in the past. The three structure members are:

- megasecs + megasecs The number of whole megaseconds elapsed since the arbitrary - point in time - secs + point in time
+ secs The number of whole seconds elapsed since the arbitrary - point in time - microsecs + point in time + microsecs The number of whole microseconds elapsed since the arbitrary - point in time + point in time
- ErlDrvPDL + ErlDrvPDL -

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 +

If certain port-specific data must be accessed from other + threads than those calling the driver callbacks, a port data lock + can be used to synchronize the operations on the data. + Currently, the only port-specific data that the emulator associates with the port data lock is the driver queue.

-

Normally a driver instance does not have a port data lock. If - the driver instance wants to use a port data lock, it has to +

Normally a driver instance has no port data lock. If + the driver instance wants to use a port data lock, it must create the port data lock by calling - driver_pdl_create(). - NOTE: Once the port data lock has been created, every - access to data associated with the port data lock has to be done - while having the port data lock locked. The port data lock is - locked, and unlocked, respectively, by use of - driver_pdl_lock(), and - driver_pdl_unlock().

+ + driver_pdl_create.

+ +

Once the port data lock has been created, every + access to data associated with the port data lock must be done + while the port data lock is locked. The port data lock is + locked and unlocked by + + driver_pdl_lock, and + + driver_pdl_unlock, respectively.

+

A port data lock is reference counted, and when the reference - count reaches zero, it will be destroyed. The emulator will at - least increment the reference count once when the lock is - created and decrement it once when the port associated with - the lock terminates. The emulator will also increment the - reference count when an async job is enqueued and decrement - it after an async job has been invoked. Besides - this, it is the responsibility of the driver to ensure that + count reaches zero, it is destroyed. The emulator at + least increments the reference count once when the lock is + created and decrements it once the port associated with + the lock terminates. The emulator also increments the + reference count when an async job is enqueued and decrements + it when an async job has been invoked. + Also, the driver is responsible for ensuring that the reference count does not reach zero before the last use of the lock by the driver has been made. The reference count - can be read, incremented, and decremented, respectively, by - use of - driver_pdl_get_refc(), - driver_pdl_inc_refc(), and - driver_pdl_dec_refc().

+ can be read, incremented, and decremented by + + driver_pdl_get_refc, + + driver_pdl_inc_refc, and + + driver_pdl_dec_refc, respectively.

- - ErlDrvTid + ErlDrvTid

Thread identifier.

-

See also: - erl_drv_thread_create(), - erl_drv_thread_exit(), - erl_drv_thread_join(), - erl_drv_thread_self(), - and - erl_drv_equal_tids(). -

+

See also + erl_drv_thread_create, + + erl_drv_thread_exit, + + erl_drv_thread_join, + + erl_drv_thread_self, and + + erl_drv_equal_tids.

- ErlDrvThreadOpts + ErlDrvThreadOpts -

- - int suggested_stack_size; - + +int suggested_stack_size;

Thread options structure passed to - erl_drv_thread_create(). - Currently the following fields exist: -

+ + erl_drv_thread_create. + The following fields exists:

- suggested_stack_size - A suggestion, in kilo-words, on how large a stack to use. A value less - than zero means default size. + suggested_stack_size + A suggestion, in kilowords, on how large a stack to use. + A value < 0 means default size. -

See also: - erl_drv_thread_opts_create(), - erl_drv_thread_opts_destroy(), - and - erl_drv_thread_create(). -

+

See also + erl_drv_thread_opts_create, + + erl_drv_thread_opts_destroy, and + + erl_drv_thread_create.

- - ErlDrvMutex + ErlDrvMutex

Mutual exclusion lock. Used for synchronizing access to shared data. - Only one thread at a time can lock a mutex. -

-

See also: - erl_drv_mutex_create(), - erl_drv_mutex_destroy(), - erl_drv_mutex_lock(), - erl_drv_mutex_trylock(), - and - erl_drv_mutex_unlock(). -

+ Only one thread at a time can lock a mutex.

+

See also + erl_drv_mutex_create, + + erl_drv_mutex_destroy, + + erl_drv_mutex_lock, + + erl_drv_mutex_trylock, and + + erl_drv_mutex_unlock.

- ErlDrvCond + ErlDrvCond -

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. -

-

See also: - erl_drv_cond_create(), - erl_drv_cond_destroy(), - erl_drv_cond_signal(), - erl_drv_cond_broadcast(), - and - erl_drv_cond_wait(). -

+

Condition variable. Used when threads must wait for a specific + condition to appear before continuing execution. Condition variables + must be used with associated mutexes.

+

See also + erl_drv_cond_create, + + erl_drv_cond_destroy, + + erl_drv_cond_signal, + + erl_drv_cond_broadcast, and + + erl_drv_cond_wait.

- ErlDrvRWLock + ErlDrvRWLock

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. -

-

See also: - erl_drv_rwlock_create(), - erl_drv_rwlock_destroy(), - erl_drv_rwlock_rlock(), - erl_drv_rwlock_tryrlock(), - erl_drv_rwlock_runlock(), - erl_drv_rwlock_rwlock(), - erl_drv_rwlock_tryrwlock(), - and - erl_drv_rwlock_rwunlock(). -

+ 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.

+

See also + erl_drv_rwlock_create, + + erl_drv_rwlock_destroy, + + erl_drv_rwlock_rlock, + + erl_drv_rwlock_tryrlock, + + erl_drv_rwlock_runlock, + + erl_drv_rwlock_rwlock, + + erl_drv_rwlock_tryrwlock, and + + erl_drv_rwlock_rwunlock.

- ErlDrvTSDKey + ErlDrvTSDKey -

Key which thread specific data can be associated with.

-

See also: - erl_drv_tsd_key_create(), - erl_drv_tsd_key_destroy(), - erl_drv_tsd_set(), - and - erl_drv_tsd_get(). -

+

Key that thread-specific data can be associated with.

+

See also + erl_drv_tsd_key_create, + + erl_drv_tsd_key_destroy, + + erl_drv_tsd_set, and + + erl_drv_tsd_get.

- ErlDrvTime + ErlDrvTime -

A signed 64-bit integer type for representation of time.

+

A signed 64-bit integer type for time representation.

- ErlDrvTimeUnit + ErlDrvTimeUnit

An enumeration of time units supported by the driver API:

- + ERL_DRV_SEC -

Seconds

+ Seconds ERL_DRV_MSEC -

Milliseconds

+ Milliseconds ERL_DRV_USEC -

Microseconds

+ Microseconds ERL_DRV_NSEC -

Nanoseconds

-
+ Nanoseconds +
- -
+ +
- voidadd_driver_entry(ErlDrvEntry *de) - Add a driver entry + voidadd_driver_entry(ErlDrvEntry + *de) + Add a driver entry. -

This function adds a driver entry to the list of drivers - known by Erlang. The init function of the de - parameter is called.

+

Adds a driver entry to the list of drivers known by Erlang. + The init + function of parameter de is called.

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. .so file) as a normal + loaded module (that is, .so file) as a normal dynamically loaded driver (loaded with the erl_ddll - interface), the caller should call driver_lock_driver before + interface), the caller is to call + + driver_lock_driver before adding driver entries.

-

Use of this function is generally deprecated.

+

Use of this function is generally deprecated.

- void *driver_alloc(ErlDrvSizeT size) - Allocate memory + void * + driver_alloc(ErlDrvSizeT size) + Allocate memory. -

This function allocates a memory block of the size specified - in size, and returns it. This only fails on out of - memory, in that case NULL is returned. (This is most +

Allocates a memory block of the size specified + in size, and returns it. This fails only on out of + memory, in which case NULL is returned. (This is most often a wrapper for malloc).

Memory allocated must be explicitly freed with a corresponding - call to driver_free (unless otherwise stated).

+ call to driver_free (unless otherwise stated).

This function is thread-safe.

- ErlDrvBinary *driver_alloc_binary(ErlDrvSizeT size) - Allocate a driver binary + ErlDrvBinary * + driver_alloc_binary(ErlDrvSizeT size) + Allocate a driver binary. -

This function allocates a driver binary with a memory block +

Allocates a driver binary with a memory block of at least size 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 - driver_free_binary (unless otherwise stated).

-

Note that a driver binary has an internal reference counter, - this means that calling driver_free_binary it may not - actually dispose of it. If it's sent to the emulator, it may + or NULL on failure (out of memory). When a driver binary has + been sent to the emulator, it must not be changed. Every + allocated binary is to be freed by a corresponding call to + + driver_free_binary (unless otherwise stated).

+

Notice that a driver binary has an internal reference counter. + This means that calling driver_free_binary, it may not + actually dispose of it. If it is sent to the emulator, it can be referenced there.

The driver binary has a field, orig_bytes, which marks the start of the data in the binary.

@@ -950,94 +1008,97 @@ typedef struct ErlIOVec {
- longdriver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*)) - Perform an asynchronous call within a driver + longdriver_async (ErlDrvPort port, unsigned + int* key, void (*async_invoke)(void*), void* async_data, void + (*async_free)(void*)) + Perform an asynchronous call within a driver. -

This function performs an asynchronous call. The function +

Performs an asynchronous call. The function async_invoke is invoked in a thread separate from the emulator thread. This enables the driver to perform time-consuming, blocking operations without blocking the emulator.

-

The async thread pool size can be set with the - +A - command line argument of erl(1). - If no async thread pool is available, the call is made - synchronously in the thread calling driver_async(). The +

The async thread pool size can be set with command-line argument + +A + in erl(1). + If an async thread pool is unavailable, the call is made + synchronously in the thread calling driver_async. The current number of async threads in the async thread pool can be - retrieved via - driver_system_info().

-

If there is a thread pool available, a thread will be - used. If the key argument is null, the threads from the + retrieved through + driver_system_info.

+

If a thread pool is available, a thread is used. + If argument key is NULL, the threads from the pool are used in a round-robin way, each call to - driver_async uses the next thread in the pool. With the - key argument set, this behaviour is changed. The two + driver_async uses the next thread in the pool. With + argument key set, this behavior is changed. The two same values of *key always get the same thread.

-

To make sure that a driver instance always uses the same +

To ensure that a driver instance always uses the same thread, the following call can be used:

-

+r = driver_async(myPort, &myKey, myData, myFunc); ]]>

It is enough to initialize myKey once for each - driver instance.

-

If a thread is already working, the calls will be + driver instance.

+

If a thread is already working, the calls are queued up and executed in order. Using the same thread for - each driver instance ensures that the calls will be made in - sequence.

+ each driver instance ensures that the calls are made in sequence.

The async_data is the argument to the functions - async_invoke and async_free. It's typically a - pointer to a structure that contains a pipe or event that + async_invoke and async_free. It is typically a + pointer to a structure containing a pipe or event that can be used to signal that the async operation completed. - The data should be freed in async_free.

-

When the async operation is done, ready_async driver - entry function is called. If ready_async is null in + The data is to be freed in async_free.

+

When the async operation is done, + + ready_async driver + entry function is called. If ready_async is NULL in the driver entry, the async_free function is called instead.

-

The return value is -1 if the driver_async call +

The return value is -1 if the driver_async call fails.

-

As of erts version 5.5.4.3 the default stack size for +

As from ERTS 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 + that is, 64 kilobyte on 32-bit architectures. + This small default size has been chosen because the + amount of async-threads can be quite large. The default stack size is enough for drivers delivered - with Erlang/OTP, but might not be sufficiently large - for other dynamically linked in drivers that use the - driver_async() functionality. A suggested stack size + with Erlang/OTP, but is possibly not 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 - +a - command line argument of - erl(1).

+ through command-line argument + +a + in erl(1).

- - unsigned intdriver_async_port_key (ErlDrvPort port) - Calculate an async key from an ErlDrvPort + + + unsigned intdriver_async_port_key (ErlDrvPort + port) + Calculate an async key from an ErlDrvPort. -

This function calculates a key for later use in driver_async(). The keys are - evenly distributed so that a fair mapping between port id's - and async thread id's is achieved.

- -

Before OTP-R16, the actual port id could be used as a key - with proper casting, but after the rewrite of the port - subsystem, this is no longer the case. With this function, you - can achieve the same distribution based on port id's as before - OTP-R16.

-
+

Calculates a key for later use in driver_async. The keys are + evenly distributed so that a fair mapping between port IDs + and async thread IDs is achieved.

+ +

Before Erlang/OTP R16, the port ID could be used as a key + with proper casting, but after the rewrite of the port + subsystem, this is no longer the case. With this function, you + can achieve the same distribution based on port IDs as before + Erlang/OTP R16.

+
- longdriver_binary_dec_refc(ErlDrvBinary *bin) - Decrement the reference count of a driver binary + long + driver_binary_dec_refc(ErlDrvBinary *bin) + Decrement the reference count of a driver binary.

Decrements the reference count on bin and returns @@ -1045,31 +1106,33 @@ typedef struct ErlIOVec {

This function is only thread-safe when the emulator with SMP support is used.

-

You should normally decrement the reference count of a - driver binary by calling - driver_free_binary(). - driver_binary_dec_refc() does not free +

The reference count of driver binary is normally to be decremented + by calling + driver_free_binary.

+

driver_binary_dec_refc does not free the binary if the reference count reaches zero. Only - use driver_binary_dec_refc() when you are sure + use driver_binary_dec_refc when you are sure not to reach a reference count of zero.

- longdriver_binary_get_refc(ErlDrvBinary *bin) - Get the reference count of a driver binary + long + driver_binary_get_refc(ErlDrvBinary *bin) + Get the reference count of a driver binary. -

Returns current reference count on bin.

+

Returns the current reference count on bin.

This function is only thread-safe when the emulator with SMP support is used.

- longdriver_binary_inc_refc(ErlDrvBinary *bin) - Increment the reference count of a driver binary + long + driver_binary_inc_refc(ErlDrvBinary *bin) + Increment the reference count of a driver binary.

Increments the reference count on bin and returns @@ -1080,143 +1143,158 @@ typedef struct ErlIOVec { - ErlDrvTermDatadriver_caller(ErlDrvPort port) - Return the process making the driver call + ErlDrvTermDatadriver_caller(ErlDrvPort + port) + Return the process making the driver call. -

This function returns the process id of the process that - made the current call to the driver. The process id can be - used with driver_send_term to send back data to the - caller. driver_caller() only returns valid data - when currently executing in one of the following driver - callbacks:

- - start - Called from open_port/2. - output - Called from erlang:send/2, and - erlang:port_command/2 - outputv - Called from erlang:send/2, and - erlang:port_command/2 - control - Called from erlang:port_control/3 - call - Called from erlang:port_call/3 - -

Note that this function is not thread-safe, not +

Returns the process ID of the process that + made the current call to the driver. The process ID can be used with + driver_send_term + to send back data to the caller. + driver_caller only returns valid data + when currently executing in one of the following driver callbacks:

+ + + start + Called from + erlang:open_port/2. + + output + Called from + erlang:send/2 and + + erlang:port_command/2. + + outputv + Called from + erlang:send/2 and + + erlang:port_command/2. + + control + Called from + erlang:port_control/3. + + call + Called from + erlang:port_call/3. + +

Notice that this function is not thread-safe, not even when the emulator with SMP support is used.

- intdriver_cancel_timer(ErlDrvPort port) - Cancel a previously set timer + int + driver_cancel_timer(ErlDrvPort port) + Cancel a previously set timer. -

This function cancels a timer set with - driver_set_timer.

-

The return value is 0.

+

Cancels a timer set with + + driver_set_timer.

+

The return value is 0.

- intdriver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2) - Compare two monitors + intdriver_compare_monitors(const ErlDrvMonitor + *monitor1, const ErlDrvMonitor *monitor2) + Compare two monitors. -

This function is used to compare two ErlDrvMonitors. It - can also be used to imply some artificial order on monitors, +

Compares two ErlDrvMonitors. + Can also be used to imply some artificial order on monitors, for whatever reason.

-

The function returns 0 if monitor1 and - monitor2 are equal, < 0 if monitor1 is less - than monitor2 and > 0 if monitor1 is greater - than monitor2.

+

Returns 0 if monitor1 and monitor2 are equal, + < 0 if monitor1 < monitor2, and + > 0 if monitor1 > monitor2.

- ErlDrvTermDatadriver_connected(ErlDrvPort port) - Return the port owner process + ErlDrvTermDatadriver_connected(ErlDrvPort + port) + Return the port owner process. -

This function returns the port owner process.

-

Note that this function is not thread-safe, not +

Returns the port owner process.

+

Notice that this function is not thread-safe, not even when the emulator with SMP support is used.

- ErlDrvPortdriver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data) - Create a new port (driver instance) + ErlDrvPortdriver_create_port(ErlDrvPort port, + ErlDrvTermData owner_pid, char* name, + ErlDrvData drv_data) + Create a new port (driver instance). -

This function creates a new port executing the same driver - code as the port creating the new port. - A short description of the arguments:

+

Creates a new port executing the same driver + code as the port creating the new port.

port The port handle of the port (driver instance) creating - the new port. + the new port. owner_pid - 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 - driver_caller(port) as owner_pid. + The process ID of the Erlang process to become + owner of the new port. This process will be linked + to the new port. You usually want to use + driver_caller(port) as owner_pid. name The port name of the new port. You usually want to - use the same port name as the driver name - (driver_name - field of the - driver_entry). + use the same port name as the driver name + ( + driver_name field of the + driver_entry). + drv_data - The driver defined handle that will be passed in subsequent - calls to driver call-backs. Note, that the - driver start call-back - will not be called for this new driver instance. - The driver defined handle is normally created in the - driver start call-back - when a port is created via - erlang:open_port/2. + The driver-defined handle that is passed in later + calls to driver callbacks. Notice that the + driver start + callback is not called for this new driver instance. + The driver-defined handle is normally created in the + driver start callback + when a port is created through + + erlang:open_port/2. + -

The caller of driver_create_port() is allowed to - manipulate the newly created port when driver_create_port() +

The caller of driver_create_port is allowed to + manipulate the newly created port when driver_create_port has returned. When port level locking - is used, the creating port is, however, only allowed to + is used, the creating port is only allowed to manipulate the newly created port until the current driver - call-back that was called by the emulator returns.

- -

When - port level locking - is used, the creating port is only allowed to manipulate - the newly created port until the current driver call-back - returns.

-
+ callback, which was called by the emulator, returns.

- intdriver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor) - Stop monitoring a process from a driver + intdriver_demonitor_process(ErlDrvPort port, + const ErlDrvMonitor *monitor) + Stop monitoring a process from a driver. -

This function cancels a monitor created earlier.

-

The function returns 0 if a monitor was removed and > 0 - if the monitor did no longer exist.

+

Cancels a monitor created earlier.

+

Returns 0 if a monitor was removed and > 0 if the monitor + no longer exists.

- ErlDrvSizeTdriver_deq(ErlDrvPort port, ErlDrvSizeT size) - Dequeue data from the head of the driver queue + ErlDrvSizeTdriver_deq(ErlDrvPort port, + ErlDrvSizeT size) + Dequeue data from the head of the driver queue. -

This function dequeues data by moving the head pointer +

Dequeues data by moving the head pointer forward in the driver queue by size bytes. The data - in the queue will be deallocated.

-

The return value is the number of bytes remaining in the queue - or -1 on failure.

-

This function can be called from an arbitrary thread if a + in the queue is deallocated.

+

Returns the number of bytes remaining in the queue on success, + otherwise -1.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1224,24 +1302,25 @@ typedef struct ErlIOVec {
- intdriver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len) - Enqueue data in the driver queue + intdriver_enq(ErlDrvPort port, char* buf, + ErlDrvSizeT len) + Enqueue data in the driver queue. -

This function enqueues data in the driver queue. The data in +

Enqueues data in the driver queue. The data in buf is copied (len bytes) and placed at the end of the driver queue. The driver queue is normally used in a FIFO way.

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.

-

When the queue contains data, the driver won't close, until + is queued by the emulator in normal Erlang message + queues). This can be useful if the driver must wait for + slow devices, and so on, and wants to yield back to the + emulator. The driver queue is implemented as an ErlIOVec.

+

When the queue contains data, the driver does not close until the queue is empty.

-

The return value is 0.

-

This function can be called from an arbitrary thread if a +

The return value is 0.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1249,34 +1328,39 @@ typedef struct ErlIOVec {
- intdriver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) - Enqueue binary in the driver queue + intdriver_enq_bin(ErlDrvPort port, + ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) + + Enqueue binary in the driver queue. -

This function enqueues a driver binary in the driver +

Enqueues a driver binary in the driver queue. The data in bin at offset with length len is placed at the end of the queue. This function - is most often faster than driver_enq, because the - data doesn't have to be copied.

-

This function can be called from an arbitrary thread if a + is most often faster than + driver_enq, + because no data must be copied.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

-

The return value is 0.

+

The return value is 0.

- intdriver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip) - Enqueue vector in the driver queue + intdriver_enqv(ErlDrvPort port, ErlIOVec *ev, + ErlDrvSizeT skip) + Enqueue vector in the driver queue. -

This function enqueues the data in ev, skipping the +

Enqueues the data in ev, skipping the first skip bytes of it, at the end of the driver - queue. It is faster than driver_enq, because the data - doesn't have to be copied.

-

The return value is 0.

-

This function can be called from an arbitrary thread if a + queue. It is faster than + driver_enq, + because no data must be copied.

+

The return value is 0.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1284,283 +1368,320 @@ typedef struct ErlIOVec {
- intdriver_failure_atom(ErlDrvPort port, char *string) - intdriver_failure_posix(ErlDrvPort port, int error) - intdriver_failure(ErlDrvPort port, int error) - Fail with error + intdriver_failure(ErlDrvPort port, int + error) + intdriver_failure_atom(ErlDrvPort port, char + *string) + intdriver_failure_posix(ErlDrvPort port, int + error) + Fail with error. -

These functions signal to Erlang that the driver has - encountered an error and should be closed. The port is - closed and the tuple {'EXIT', error, Err}, is sent to +

Signals to Erlang that the driver has + encountered an error and is to be closed. The port is + closed and the tuple {'EXIT', error, Err} is sent to the port owner process, where error is an error atom (driver_failure_atom and - driver_failure_posix), or an integer + driver_failure_posix) or an integer (driver_failure).

-

The driver should fail only when in severe error situations, - when the driver cannot possibly keep open, for instance +

The driver is to fail only when in severe error situations, + when the driver cannot possibly keep open, for example, buffer allocation gets out of memory. For normal errors it is more appropriate to send error codes with - driver_output.

-

The return value is 0.

+ driver_output.

+

The return value is 0.

- intdriver_failure_eof(ErlDrvPort port) - Fail with EOF + intdriver_failure_eof(ErlDrvPort + port) + Fail with EOF. -

This function signals to erlang that the driver has - encountered an EOF and should be closed, unless the port was - opened with the eof option, in that case eof is sent - to the port. Otherwise, the port is closed and an +

Signals to Erlang that the driver has + encountered an EOF and is to be closed, unless the port was + opened with option eof, in which case eof is sent + to the port. Otherwise the port is closed and an 'EXIT' message is sent to the port owner process.

-

The return value is 0.

+

The return value is 0.

voiddriver_free(void *ptr) - Free an allocated memory block + Free an allocated memory block. -

This function frees the memory pointed to by ptr. The - memory should have been allocated with - driver_alloc. All allocated memory should be - deallocated, just once. There is no garbage collection in +

Frees the memory pointed to by ptr. The + memory is to have been allocated with + driver_alloc. All allocated memory is to be + deallocated, only once. There is no garbage collection in drivers.

This function is thread-safe.

- voiddriver_free_binary(ErlDrvBinary *bin) - Free a driver binary + void + driver_free_binary(ErlDrvBinary *bin) + Free a driver binary. -

This function frees a driver binary bin, allocated - previously with driver_alloc_binary. Since binaries - in Erlang are reference counted, the binary may still be - around.

+

Frees a driver binary bin, allocated previously with + + driver_alloc_binary. As binaries + in Erlang are reference counted, the binary can still be around.

This function is only thread-safe when the emulator with SMP support is used.

- ErlDrvTermDatadriver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor) - Retrieve the process id from a monitor + ErlDrvTermData + driver_get_monitored_process(ErlDrvPort port, const + ErlDrvMonitor *monitor) + Retrieve the process ID from a monitor. -

The function returns the process id associated with a living - monitor. It can be used in the process_exit call-back to - get the process identification for the exiting process.

-

The function returns driver_term_nil if the monitor - no longer exists.

+

Returns the process ID associated with a living + monitor. It can be used in the + + process_exit callback to + get the process identification for the exiting process.

+

Returns driver_term_nil if the monitor no longer exists.

- intdriver_get_now(ErlDrvNowData *now) - Read a system timestamp + int + driver_get_now(ErlDrvNowData *now) + Read a system time stamp. -

This function is deprecated! Do not use it! - Use erl_drv_monotonic_time() - (perhaps in combination with - erl_drv_time_offset()) - instead.

-

This function reads a timestamp into the memory pointed to by - the parameter now. See the description of ErlDrvNowData for - specification of its fields.

-

The return value is 0 unless the now pointer is not - valid, in which case it is < 0.

+ +

This function is deprecated. Do not use it. Use + + erl_drv_monotonic_time (perhaps in combination with + + erl_drv_time_offset) instead.

+
+

Reads a time stamp into the memory pointed to by + parameter now. For information about specific fields, see + ErlDrvNowData.

+

The return value is 0, unless the now pointer is + invalid, in which case it is < 0.

- intdriver_lock_driver(ErlDrvPort port) - Make sure the driver is never unloaded + intdriver_lock_driver(ErlDrvPort + port) + Ensure the driver is never unloaded. -

This function locks the driver used by the port port +

Locks the driver used by the port port 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.

+ statically linked-in drivers.

- ErlDrvTermDatadriver_mk_atom(char* string) - Make an atom from a name + ErlDrvTermDatadriver_mk_atom(char* + string) + Make an atom from a name. -

This function returns an atom given a name - string. The atom is created and won't change, so the - return value may be saved and reused, which is faster than +

Returns an atom given a name + string. The atom is created and does not change, so the + return value can be saved and reused, which is faster than looking up the atom several times.

-

Note that this function is not thread-safe, not +

Notice that this function is not thread-safe, not even when the emulator with SMP support is used.

- ErlDrvTermDatadriver_mk_port(ErlDrvPort port) - Make a erlang term port from a port + ErlDrvTermDatadriver_mk_port(ErlDrvPort + port) + Make an Erlang term port from a port. -

This function converts a port handle to the erlang term - format, usable in the erl_drv_output_term(), and erl_drv_send_term() functions.

-

Note that this function is not thread-safe, not +

Converts a port handle to the Erlang term format, usable in + + erl_drv_output_term and + + erl_drv_send_term.

+

Notice that this function is not thread-safe, not even when the emulator with SMP support is used.

- intdriver_monitor_process(ErlDrvPort port, ErlDrvTermData process, ErlDrvMonitor *monitor) - Monitor a process from a driver + intdriver_monitor_process(ErlDrvPort port, + ErlDrvTermData process, ErlDrvMonitor *monitor) + Monitor a process from a driver. -

Start monitoring a process from a driver. When a process is - monitored, a process exit will result in a call to the - provided process_exit call-back - in the ErlDrvEntry +

Starts monitoring a process from a driver. When a process is + monitored, a process exit results in a call to the provided + + process_exit callback + in the ErlDrvEntry structure. The ErlDrvMonitor structure is filled in, for later removal or compare.

-

The process parameter should be the return value of an - earlier call to driver_caller or driver_connected call.

-

The function returns 0 on success, < 0 if no call-back is - provided and > 0 if the process is no longer alive.

+

Parameter process is to be the return value of an + earlier call to + driver_caller or + driver_connected + call.

+

Returns 0 on success, < 0 if no callback is + provided, and > 0 if the process is no longer alive.

- intdriver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len) - Send data from driver to port owner + intdriver_output(ErlDrvPort port, char *buf, + ErlDrvSizeT len) + Send data from driver to port owner. -

The driver_output 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 +

Sends data from the driver up to the emulator. The data is received + as terms or binary data, depending on how the driver port was opened.

The data is queued in the port owner process' message - queue. Note that this does not yield to the emulator. (Since - the driver and the emulator run in the same thread.)

-

The parameter buf points to the data to send, and + queue. Notice that this does not yield to the emulator (as + the driver and the emulator run in the same thread).

+

Parameter buf points to the data to send, and len is the number of bytes.

-

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.)

+

The return value for all output functions is 0 for normal use. + If the driver is used for distribution, it can fail and return + -1.

- intdriver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len) - Send data from a driver binary to port owner + intdriver_output_binary(ErlDrvPort port, char + *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, + ErlDrvSizeT len) + Send data from a driver binary to port owner. -

This function sends data to port owner process from a - driver binary, it has a header buffer (hbuf - and hlen) just like driver_output2. The - hbuf parameter can be NULL.

-

The parameter offset is an offset into the binary and +

Sends data to a port owner process from a + driver binary. It has a header buffer (hbuf + and hlen) just like + driver_output2. + Parameter hbuf can be NULL.

+

Parameter offset is an offset into the binary and len is the number of bytes to send.

-

Driver binaries are created with driver_alloc_binary.

+

Driver binaries are created with + + driver_alloc_binary.

The data in the header is sent as a list and the binary as an Erlang binary in the tail of the list.

-

E.g. if hlen is 2, then the port owner process will - receive >]]]>.

-

The return value is 0 for normal use.

-

Note that, using the binary syntax in Erlang, the driver +

For example, if hlen is 2, the port owner process + receives >]]]>.

+

The return value is 0 for normal use.

+

Notice that, using the binary syntax in Erlang, the driver application can match the header directly from the binary, - so the header can be put in the binary, and hlen can be set - to 0.

+ so the header can be put in the binary, and hlen can be set + to 0.

- intdriver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n) - Send term data from driver to port owner + intdriver_output_term(ErlDrvPort port, + ErlDrvTermData* term, int n) + Send term data from driver to port owner. -

driver_output_term() is deprecated and will - be removed in the OTP-R17 release. Use - erl_drv_output_term() - instead.

-
-

The parameters term and n do the same thing - as in erl_drv_output_term().

-

Note that this function is not thread-safe, not + +

This function is deprecated. + Use + erl_drv_output_terminstead.

+ +

Parameters term and n work as in + + erl_drv_output_term.

+

Notice that this function is not thread-safe, not even when the emulator with SMP support is used.

- intdriver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len) - Send data and binary data to port owner + intdriver_output2(ErlDrvPort port, char *hbuf, + ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len) + Send data and binary data to port owner. -

The driver_output2 function first sends hbuf +

First sends hbuf (length in hlen) data as a list, regardless of port - settings. Then buf is sent as a binary or list. - E.g. if hlen is 3 then the port owner process will - receive [H1, H2, H3 | T].

+ settings. Then sends buf as a binary or list. + For example, if hlen is 3, the port owner process + receives [H1, H2, H3 | T].

The point of sending data as a list header, is to facilitate matching on the data received.

-

The return value is 0 for normal use.

+

The return value is 0 for normal use.

- intdriver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip) - Send vectorized data to port owner + intdriver_outputv(ErlDrvPort port, char* hbuf, + ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip) + Send vectorized data to port owner. -

This function sends data from an IO vector, ev, to +

Sends data from an I/O vector, ev, to the port owner process. It has a header buffer (hbuf - and hlen), just like driver_output2.

-

The skip parameter is a number of bytes to skip of + and hlen), just like + driver_output2.

+

Parameter skip is a number of bytes to skip of the ev vector from the head.

You get vectors of ErlIOVec type from the driver - queue (see below), and the outputv driver entry - function. You can also make them yourself, if you want to + queue (see below), and the + outputv + driver entry function. You can also make them yourself, if you want to send several ErlDrvBinary buffers at once. Often - it is faster to use driver_output or - driver_output_binary.

-

E.g. if hlen is 2 and ev points to an array of - three binaries, the port owner process will receive >, <> | <>]]]>.

-

The return value is 0 for normal use.

-

The comment for driver_output_binary applies for - driver_outputv too.

+ it is faster to use + driver_output or + .

+

For example, if hlen is 2 and ev points to an + array of three binaries, the port owner process receives + >, <> | <>]]]>.

+

The return value is 0 for normal use.

+

The comment for driver_output_binary also applies for + driver_outputv.

- ErlDrvPDLdriver_pdl_create(ErlDrvPort port) - Create a port data lock + ErlDrvPDL + driver_pdl_create(ErlDrvPort port) + Create a port data lock. -

This function creates a port data lock associated with - the port. NOTE: Once a port data lock has - been created, it has to be locked during all operations - on the driver queue of the port.

-

On success a newly created port data lock is returned. On - failure NULL is returned. driver_pdl_create() will - fail if port is invalid or if a port data lock already has +

Creates a port data lock associated with the port.

+ +

Once a port data lock has been created, it must be locked during + all operations on the driver queue of the port.

+
+

Returns a newly created port data lock on success, + otherwise NULL. The function fails + if port is invalid or if a port data lock already has been associated with the port.

- longdriver_pdl_dec_refc(ErlDrvPDL pdl) + longdriver_pdl_dec_refc(ErlDrvPDL + pdl) -

This function decrements the reference count of +

Decrements the reference count of the port data lock passed as argument (pdl).

The current reference count after the decrement has been performed is returned.

@@ -1569,22 +1690,24 @@ typedef struct ErlIOVec {
- longdriver_pdl_get_refc(ErlDrvPDL pdl) + long + driver_pdl_get_refc(ErlDrvPDL pdl) -

This function returns the current reference count of +

Returns the current reference count of the port data lock passed as argument (pdl).

This function is thread-safe.

- longdriver_pdl_inc_refc(ErlDrvPDL pdl) + long + driver_pdl_inc_refc(ErlDrvPDL pdl) -

This function increments the reference count of +

Increments the reference count of the port data lock passed as argument (pdl).

The current reference count after the increment has been performed is returned.

@@ -1593,41 +1716,42 @@ typedef struct ErlIOVec {
- voiddriver_pdl_lock(ErlDrvPDL pdl) - Lock port data lock + void + driver_pdl_lock(ErlDrvPDL pdl) + Lock port data lock. -

This function locks the port data lock passed as argument - (pdl).

+

Locks the port data lock passed as argument (pdl).

This function is thread-safe.

- voiddriver_pdl_unlock(ErlDrvPDL pdl) - Unlock port data lock + void + driver_pdl_unlock(ErlDrvPDL pdl) + Unlock port data lock. -

This function unlocks the port data lock passed as argument - (pdl).

+

Unlocks the port data lock passed as argument (pdl).

This function is thread-safe.

- SysIOVec *driver_peekq(ErlDrvPort port, int *vlen) - Get the driver queue as a vector + SysIOVec *driver_peekq(ErlDrvPort port, int + *vlen) + Get the driver queue as a vector. -

This function retrieves the driver queue as a pointer to an +

Retrieves the driver queue as a pointer to an array of SysIOVecs. It also returns the number of elements in vlen. This is one of two ways to get data out of the queue.

Nothing is removed from the queue by this function, that must be done - with driver_deq.

+ with driver_deq.

The returned array is suitable to use with the Unix system call writev.

-

This function can be called from an arbitrary thread if a +

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1635,22 +1759,19 @@ typedef struct ErlIOVec {
- ErlDrvSizeTdriver_peekqv(ErlDrvPort port, ErlIOVec *ev) - Get the driver queue as an IO vector + ErlDrvSizeTdriver_peekqv(ErlDrvPort port, + ErlIOVec *ev) + Get the driver queue as an I/O vector. -

- This function retrieves the driver queue into a supplied +

Retrieves the driver queue into a supplied ErlIOVec ev. It also returns the queue size. - This is one of two ways to get data out of the queue. -

-

- If ev is NULL all ones i.e. -1 type cast to - ErlDrvSizeT is returned. -

+ This is one of two ways to get data out of the queue.

+

If ev is NULL, all ones that is -1 type cast to + ErlDrvSizeT are returned.

Nothing is removed from the queue by this function, that must be done - with driver_deq.

-

This function can be called from an arbitrary thread if a + with driver_deq.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1658,15 +1779,16 @@ typedef struct ErlIOVec {
- intdriver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len) - Push data at the head of the driver queue + intdriver_pushq(ErlDrvPort port, char* buf, + ErlDrvSizeT len) + Push data at the head of the driver queue. -

This function puts data at the head of the driver queue. The +

Puts data at the head of the driver queue. The data in buf is copied (len bytes) and placed at the beginning of the queue.

-

The return value is 0.

-

This function can be called from an arbitrary thread if a +

The return value is 0.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1674,34 +1796,38 @@ typedef struct ErlIOVec {
- intdriver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) - Push binary at the head of the driver queue + intdriver_pushq_bin(ErlDrvPort port, + ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) + + Push binary at the head of the driver queue. -

This function puts data in the binary bin, at +

Puts data in the binary bin, at offset with length len at the head of the driver queue. It is most often faster than - driver_pushq, because the data doesn't have to be - copied.

-

This function can be called from an arbitrary thread if a + driver_pushq, + because no data must be copied.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

-

The return value is 0.

+

The return value is 0.

- intdriver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip) - Push vector at the head of the driver queue + intdriver_pushqv(ErlDrvPort port, ErlIOVec + *ev, ErlDrvSizeT skip) + Push vector at the head of the driver queue. -

This function puts the data in ev, skipping the first +

Puts the data in ev, skipping the first skip bytes of it, at the head of the driver queue. - It is faster than driver_pushq, because the data - doesn't have to be copied.

-

The return value is 0.

-

This function can be called from an arbitrary thread if a + It is faster than + driver_pushq, + because no data must be copied.

+

The return value is 0.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1709,24 +1835,26 @@ typedef struct ErlIOVec {
- intdriver_read_timer(ErlDrvPort port, unsigned long *time_left) - Read the time left before timeout + intdriver_read_timer(ErlDrvPort port, unsigned + long *time_left) + Read the time left before time-out. -

This function reads the current time of a timer, and places +

Reads the current time of a timer, and places the result in time_left. This is the time in - milliseconds, before the timeout will occur.

-

The return value is 0.

+ milliseconds, before the time-out occurs.

+

The return value is 0.

- void *driver_realloc(void *ptr, ErlDrvSizeT size) - Resize an allocated memory block + void * + driver_realloc(void *ptr, ErlDrvSizeT size) + Resize an allocated memory block. -

This function resizes a memory block, either in place, or by - allocating a new block, copying the data and freeing the old +

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), NULL is returned. (This is most often a wrapper for realloc.)

@@ -1735,120 +1863,132 @@ typedef struct ErlIOVec {
- ErlDrvBinary *driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) - Resize a driver binary + ErlDrvBinary * + driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) + + Resize a driver binary. -

This function resizes a driver binary, while keeping the - data. The resized driver binary is returned. On failure (out - of memory), NULL is returned.

+

Resizes a driver binary, while keeping the data.

+

Returns the resized driver binary on success. Returns NULL + on failure (out of memory).

This function is only thread-safe when the emulator with SMP support is used.

- intdriver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on) - Provide an event for having the emulator call the driver + intdriver_select(ErlDrvPort port, ErlDrvEvent + event, int mode, int on) + Provides an event for having the emulator call the driver. +

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.

-

The event argument identifies an OS-specific event object. - On Unix systems, the functions select/poll are used. The - event object must be a socket or pipe (or other object that + when something has occurred asynchronously.

+

Parameter event identifies an OS-specific event object. + On Unix systems, the functions select/poll are used. + The event object must be a socket or pipe (or other object that select/poll can use). - On windows, the Win32 API function WaitForMultipleObjects - is used. This places other restrictions on the event object. - Refer to the Win32 SDK documentation.

-

The on parameter should be 1 for setting events + On Windows, the Win32 API function WaitForMultipleObjects + is used. This places other restrictions on the event object; + see the Win32 SDK documentation.

+

Parameter on is to be 1 for setting events and 0 for clearing them.

-

The mode argument is a bitwise-or combination of - ERL_DRV_READ, ERL_DRV_WRITE and ERL_DRV_USE. +

Parameter mode is a bitwise OR combination of + ERL_DRV_READ, ERL_DRV_WRITE, and ERL_DRV_USE. The first two specify whether to wait for read events and/or write - events. A fired read event will call - ready_input - while a fired write event will call - ready_output. -

- -

Some OS (Windows) do not differentiate between read and write events. - The call-back for a fired event then only depends on the value of mode.

-
-

ERL_DRV_USE 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 driver_select has - returned. Another thread may still be using the event object - internally. To safely close an event object call - driver_select with ERL_DRV_USE and on==0. That - will clear all events and then call - stop_select - when it is safe to close the event object. - ERL_DRV_USE should be set together with the first event - for an event object. It is harmless to set ERL_DRV_USE - even though it already has been done. Clearing all events but keeping - ERL_DRV_USE set will indicate that we are using the event - object and probably will set events for it again.

- -

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 ERL_DRV_USE and - stop_select to make sure that event objects are closed in a safe way.

-
-

The return value is 0 (failure, -1, only if the - ready_input/ready_output is - NULL).

+ events. A fired read event calls + + ready_input and a fired write event calls + + ready_output.

+ +

Some OS (Windows) do not differentiate between read and write + events. The callback for a fired event then only depends on the + value of mode.

+
+

ERL_DRV_USE 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 driver_select has + returned. Another thread can still be using the event object + internally. To safely close an event object, call + driver_select with ERL_DRV_USE and on==0, which + clears all events. Then call + + stop_select when it is safe to close the event + object. ERL_DRV_USE is to be set together with the first event + for an event object. It is harmless to set ERL_DRV_USE + even if it already has been done. Clearing all events but keeping + ERL_DRV_USE set indicates that we are using the event + object and probably will set events for it again.

+ +

ERL_DRV_USE was added in Erlang/OTP R13. Old drivers still + work as before, but it is recommended to update them to use + ERL_DRV_USE and stop_select to ensure that event + objects are closed in a safe way.

+
+

The return value is 0, unless + ready_input/ready_output is NULL, in which case + it is -1.

- intdriver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) - Send term data to other process than port owner process + intdriver_send_term(ErlDrvPort port, + ErlDrvTermData receiver, ErlDrvTermData* term, int n) + Send term data to other process than port owner process. + -

driver_send_term() is deprecated and will - be removed in the OTP-R17 release. Use - erl_drv_send_term() - instead.

-

Also note that parameters of driver_send_term() - cannot be properly checked by the runtime system when - executed by arbitrary threads. This may cause the - driver_send_term() function not to fail when - it should.

-
-

The parameters term and n do the same thing - as in erl_drv_output_term().

+ +

This function is deprecated. + Use + erl_drv_send_term instead.

+
+ +

The parameters of this function + cannot be properly checked by the runtime system when + executed by arbitrary threads. This can cause the + function not to fail when it should.

+
+

Parameters term and n work as in + + erl_drv_output_term.

This function is only thread-safe when the emulator with SMP support is used.

- intdriver_set_timer(ErlDrvPort port, unsigned long time) - Set a timer to call the driver + intdriver_set_timer(ErlDrvPort port, unsigned + long time) + Set a timer to call the driver. -

This function sets a timer on the driver, which will count - down and call the driver when it is timed out. The - time parameter is the time in milliseconds before the - timer expires.

-

When the timer reaches 0 and expires, the driver entry - function timeout is called.

-

Note that there is only one timer on each driver instance; - setting a new timer will replace an older one.

-

Return value is 0 (-1 only when the timeout driver - function is NULL).

+

Sets a timer on the driver, which will count + down and call the driver when it is timed out. Parameter + time is the time in milliseconds before the timer expires.

+

When the timer reaches 0 and expires, the driver entry + function + timeout is called.

+

Notice that only one timer exists on each driver instance; + setting a new timer replaces an older one.

+

Return value is 0, unless the timeout + driver function is NULL, in which case it is -1.

- ErlDrvSizeTdriver_sizeq(ErlDrvPort port) - Return the size of the driver queue + ErlDrvSizeT + driver_sizeq(ErlDrvPort port) + Return the size of the driver queue. -

This function returns the number of bytes currently in the - driver queue.

-

This function can be called from an arbitrary thread if a +

Returns the number of bytes currently in the driver queue.

+

This function can be called from any thread if a port data lock associated with the port is locked by the calling thread during the call.

@@ -1856,585 +1996,523 @@ typedef struct ErlIOVec {
- voiddriver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size) - Get information about the Erlang runtime system + voiddriver_system_info(ErlDrvSysInfo + *sys_info_ptr, size_t size) + Get information about the Erlang runtime system. -

This function will write information about the Erlang runtime - system into the - ErlDrvSysInfo +

Writes information about the Erlang runtime system into the + ErlDrvSysInfo structure referred to by the first argument. The second - argument should be the size of the - ErlDrvSysInfo - structure, i.e., sizeof(ErlDrvSysInfo).

-

See the documentation of the - ErlDrvSysInfo - structure for information about specific fields.

+ argument is to be the size of the + ErlDrvSysInfo + structure, that is, sizeof(ErlDrvSysInfo).

+

For information about specific fields, see + ErlDrvSysInfo.

- - ErlDrvSizeTdriver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len) - Collect data segments into a buffer + + + ErlDrvSizeTdriver_vec_to_buf(ErlIOVec *ev, + char *buf, ErlDrvSizeT len) + Collect data segments into a buffer. -

This function collects several segments of data, referenced +

Collects several segments of data, referenced by ev, by copying them in order to the buffer buf, of the size len.

If the data is to be sent from the driver to the port owner - process, it is faster to use driver_outputv.

-

The return value is the space left in the buffer, i.e. if - the ev contains less than len bytes it's the - difference, and if ev contains len 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 + process, it is faster to use + driver_outputv.

+

The return value is the space left in the buffer, that is, if + ev contains less than len bytes it is the + difference, and if ev contains len bytes or more, + it is 0. This is faster if there is more than one header byte, + as the binary syntax can construct integers directly from the binary.

- voiderl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high) - Set and get limits for busy port message queue + voiderl_drv_busy_msgq_limits(ErlDrvPort port, + ErlDrvSizeT *low, ErlDrvSizeT *high) + Set and get limits for busy port message queue.

Sets and gets limits that will be used for controling the - busy state of the port message queue.

-

The port message queue will be set into a busy - state when the amount of command data queued on the - message queue reaches the high limit. The port - message queue will be set into a not busy state when the - amount of command data queued on the message queue falls - below the low limit. Command data is in this - context data passed to the port using either - Port ! {Owner, {command, Data}}, or - port_command/[2,3]. Note that these limits - only concerns command data that have not yet reached the - port. The busy port - feature can be used for data that has reached the port.

- -

Valid limits are values in the range - [ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]. - Limits will be automatically adjusted to be sane. That is, - the system will adjust values so that the low limit used is - lower than or equal to the high limit used. By default the high - limit will be 8 kB and the low limit will be 4 kB.

- -

By passing a pointer to an integer variable containing - the value ERL_DRV_BUSY_MSGQ_READ_ONLY, currently used - limit will be read and written back to the integer variable. - A new limit can be set by passing a pointer to an integer - variable containing a valid limit. The passed value will be - written to the internal limit. The internal limit will then - be adjusted. After this the adjusted limit will be written - back to the integer variable from which the new value was - read. Values are in bytes.

- -

The busy message queue feature can be disabled either - by setting the ERL_DRV_FLAG_NO_BUSY_MSGQ - driver flag - in the driver_entry - used by the driver, or by calling this function with - ERL_DRV_BUSY_MSGQ_DISABLED as a limit (either low or - high). When this feature has been disabled it cannot be - enabled again. When reading the limits both of them - will be ERL_DRV_BUSY_MSGQ_DISABLED, if this - feature has been disabled.

- -

Processes sending command data to the port will be suspended - if either the port is busy or if the port message queue is - busy. Suspended processes will be resumed when neither the - port is busy, nor the port message queue is busy.

- -

For information about busy port functionality - see the documentation of the - set_busy_port() - function.

-
-
- - - voiderl_drv_cond_broadcast(ErlDrvCond *cnd) - Broadcast on a condition variable + busy state of the port message queue.

+

The port message queue is set into a busy + state when the amount of command data queued on the + message queue reaches the high limit. The port + message queue is set into a not busy state when the + amount of command data queued on the message queue falls + below the low limit. Command data is in this + context data passed to the port using either + Port ! {Owner, {command, Data}} or + port_command/[2,3]. Notice that these limits + only concerns command data that have not yet reached the + port. The busy port + feature can be used for data that has reached the port.

+

Valid limits are values in the range + [ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]. + Limits are automatically adjusted to be sane. That is, + the system adjusts values so that the low limit used is + lower than or equal to the high limit used. By default the high + limit is 8 kB and the low limit is 4 kB.

+

By passing a pointer to an integer variable containing + the value ERL_DRV_BUSY_MSGQ_READ_ONLY, the currently used + limit is read and written back to the integer variable. + A new limit can be set by passing a pointer to an integer + variable containing a valid limit. The passed value is + written to the internal limit. The internal limit is then + adjusted. After this the adjusted limit is written + back to the integer variable from which the new value was + read. Values are in bytes.

+

The busy message queue feature can be disabled either + by setting the ERL_DRV_FLAG_NO_BUSY_MSGQ + driver flag + in the driver_entry + used by the driver, or by calling this function with + ERL_DRV_BUSY_MSGQ_DISABLED as a limit (either low or + high). When this feature has been disabled, it cannot be + enabled again. When reading the limits, both are + ERL_DRV_BUSY_MSGQ_DISABLED if this + feature has been disabled.

+

Processes sending command data to the port are suspended + if either the port is busy or if the port message queue is + busy. Suspended processes are resumed when neither the + port or the port message queue is busy.

+

For information about busy port functionality, see + set_busy_port.

+ +
+ + + voiderl_drv_cond_broadcast(ErlDrvCond + *cnd) + Broadcast on a condition variable. -

Arguments:

- - cnd - A pointer to a condition variable to broadcast on. - -

This function broadcasts on a condition variable. That is, if - other threads are waiting on the condition variable being - broadcast on, all of them will be woken. -

+

Broadcasts on a condition variable. That is, if + other threads are waiting on the condition variable being + broadcast on, all of them are woken.

+

cnd is a pointer to a condition variable to broadcast on.

This function is thread-safe.

- ErlDrvCond *erl_drv_cond_create(char *name) - Create a condition variable + ErlDrvCond *erl_drv_cond_create(char + *name) + Create a condition variable. -

Arguments:

- - name - A string identifying the created condition variable. It - will be used to identify the condition variable in planned - future debug functionality. - - -

This function creates a condition variable and returns a - pointer to it. On failure NULL is returned. The driver - creating the condition variable has the responsibility of - destroying it before the driver is unloaded.

+

Creates a condition variable and returns a pointer to it.

+

name is a string identifying the created condition variable. + It is used to identify the condition variable in planned + future debug functionality.

+

Returns NULL on failure. The driver + creating the condition variable is responsibile for + destroying it before the driver is unloaded.

This function is thread-safe.

- voiderl_drv_cond_destroy(ErlDrvCond *cnd) - Destroy a condition variable + voiderl_drv_cond_destroy(ErlDrvCond + *cnd) + Destroy a condition variable. -

Arguments:

- - cnd - A pointer to a condition variable to destroy. - -

This function destroys a condition variable previously - created by - erl_drv_cond_create(). -

-

This function is thread-safe.

-
-
- - char *erl_drv_cond_name(ErlDrvCond *cnd) - Get name of driver mutex. - - -

Arguments:

- - cnd - A pointer to an initialized condition. - -

- Returns a pointer to the name of the condition. -

- -

This function is intended for debugging purposes only.

-
-
-
- - - voiderl_drv_cond_signal(ErlDrvCond *cnd) - Signal on a condition variable +

Destroys a condition variable previously created by + + erl_drv_cond_create.

+

cnd is a pointer to a condition variable to destroy.

+

This function is thread-safe.

+ +
+ + + char *erl_drv_cond_name(ErlDrvCond + *cnd) + Get name of driver mutex. + + +

Returns a pointer to the name of the condition.

+

cnd is a pointer to an initialized condition.

+ +

This function is intended for debugging purposes only.

+
+
+
+ + + voiderl_drv_cond_signal(ErlDrvCond + *cnd) + Signal on a condition variable. -

Arguments:

- - cnd - A pointer to a condition variable to signal on. - -

This function signals on a condition variable. That is, if - other threads are waiting on the condition variable being - signaled, one of them will be woken. -

+

Signals on a condition variable. That is, if + other threads are waiting on the condition variable being + signaled, one of them is woken.

+

cnd is a pointer to a condition variable to signal on.

This function is thread-safe.

- voiderl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx) - Wait on a condition variable + voiderl_drv_cond_wait(ErlDrvCond *cnd, + ErlDrvMutex *mtx) + Wait on a condition variable. -

Arguments:

- - cnd - A pointer to a condition variable to wait on. - mtx - A pointer to a mutex to unlock while waiting. - - - -

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. -

-

erl_drv_cond_wait() might return even though - no-one has signaled or broadcast on the condition - variable. Code calling erl_drv_cond_wait() should - always be prepared for erl_drv_cond_wait() - returning even though the condition that the thread was - waiting for hasn't occurred. That is, when returning from - erl_drv_cond_wait() always check if the condition - has occurred, and if not call erl_drv_cond_wait() - again. -

+

Waits on a condition variable. The calling + thread is blocked until another thread wakes it by signaling + or broadcasting on the condition variable. Before the calling + thread is blocked, it unlocks the mutex passed as argument. + When the calling thread is woken, it locks the same mutex before + returning. That is, the mutex currently must be locked by + the calling thread when calling this function.

+

cnd is a pointer to a condition variable to wait on. + mtx is a pointer to a mutex to unlock while waiting.

+ +

erl_drv_cond_wait can return even if + no one has signaled or broadcast on the condition + variable. Code calling erl_drv_cond_wait is + always to be prepared for erl_drv_cond_wait + returning even if the condition that the thread was + waiting for has not occurred. That is, when returning from + erl_drv_cond_wait, always check if the condition + has occurred, and if not call erl_drv_cond_wait again.

+

This function is thread-safe.

- interl_drv_consume_timeslice(ErlDrvPort port, int percent) + interl_drv_consume_timeslice(ErlDrvPort port, + int percent) Give the runtime system a hint about how much CPU time the - current driver callback call has consumed + current driver callback call has consumed. -

Arguments:

+

Gives the runtime system a hint about how much CPU time the current + driver callback call has consumed since the last hint, or since the + the start of the callback if no previous hint has been given.

port Port handle of the executing port. percent Approximate consumed fraction of a full - time-slice in percent. + time-slice in percent. -

Give the runtime system a hint about how much CPU time the - current driver callback call has consumed since last hint, or - since the start of the callback if no previous hint has been given. - The time is given as a fraction, in percent, of a full time-slice - that a port is allowed to execute before it should surrender the - CPU to other runnable ports or processes. Valid range is - [1, 100]. The scheduling time-slice is not an exact entity, - but can usually be approximated to about 1 millisecond.

- -

Note that it is up to the runtime system to determine if and - how to use this information. Implementations on some platforms - may use other means in order to determine the consumed fraction - of the time-slice. Lengthy driver callbacks should regardless of - this frequently call the erl_drv_consume_timeslice() - function in order to determine if it is allowed to continue - execution or not.

- -

erl_drv_consume_timeslice() returns a non-zero value - if the time-slice has been exhausted, and zero if the callback is - allowed to continue execution. If a non-zero value is - returned the driver callback should return as soon as possible in - order for the port to be able to yield.

- -

This function is provided to better support co-operative scheduling, - improve system responsiveness, and to make it easier to prevent - misbehaviors of the VM due to a port monopolizing a scheduler thread. - It can be used when dividing length work into a number of repeated - driver callback calls without the need to use threads. Also see the - important warning text at the - beginning of this document.

-
-
- - - ErlDrvTimeerl_drv_convert_time_unit(ErlDrvTime val, ErlDrvTimeUnit from, ErlDrvTimeUnit to) - Convert time unit of a time value - - -

Arguments:

- - val - Value to convert time unit for. - from - Time unit of val. - to - Time unit of returned value. - -

Converts the val value of time unit from to - the corresponding value of time unit to. The result is - rounded using the floor function.

-

Returns ERL_DRV_TIME_ERROR if called with an invalid - time unit argument.

-

See also:

- - ErlDrvTime - ErlDrvTimeUnit - -
-
- - - interl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2) - Compare thread identifiers for equality - - -

Arguments:

+

The time is specified as a fraction, in percent, of a full time-slice + that a port is allowed to execute before it is to surrender the + CPU to other runnable ports or processes. Valid range is + [1, 100]. The scheduling time-slice is not an exact entity, + but can usually be approximated to about 1 millisecond.

+

Notice that it is up to the runtime system to determine if and + how to use this information. Implementations on some platforms + can use other means to determine the consumed fraction + of the time-slice. Lengthy driver callbacks should, regardless of + this frequently, call this function to determine if it is allowed + to continue execution or not.

+

This function returns a non-zero value + if the time-slice has been exhausted, and zero if the callback is + allowed to continue execution. If a non-zero value is + returned, the driver callback is to return as soon as possible in + order for the port to be able to yield.

+

This function is provided to better support co-operative scheduling, + improve system responsiveness, and to make it easier to prevent + misbehaviors of the VM because of a port monopolizing a scheduler + thread. It can be used when dividing lengthy work into some repeated + driver callback calls, without the need to use threads.

+

See also the important warning + text at the beginning of this manual page.

+
+
+ + + ErlDrvTimeerl_drv_convert_time_unit(ErlDrvTime + val, ErlDrvTimeUnit from, ErlDrvTimeUnit to) + Convert time unit of a time value. + + +

Converts the val value of time unit from to + the corresponding value of time unit to. The result is + rounded using the floor function.

- tid1 - A thread identifier. - tid2 - A thread identifier. + val + Value to convert time unit for. + from + Time unit of val. + to + Time unit of returned value. -

This function compares two thread identifiers for equality, - and returns 0 it they aren't equal, and - a value not equal to 0 if they are equal.

-

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 erl_drv_equal_tids() might not give - the expected result. -

+

Returns ERL_DRV_TIME_ERROR if called with an invalid + time unit argument.

+

See also + ErlDrvTime and + + ErlDrvTimeUnit.

+
+
+ + + interl_drv_equal_tids(ErlDrvTid tid1, + ErlDrvTid tid2) + Compare thread identifiers for equality. + + +

Compares two thread identifiers, tid1 and tid2, + for equality.

+

Returns 0 it they are not equal, and a value not equal to + 0 if they are equal.

+ +

A thread identifier can be reused very quickly after + a thread has terminated. Therefore, if a thread + corresponding to one of the involved thread identifiers + has terminated since the thread identifier was saved, + the result of erl_drv_equal_tids does possibly not give + the expected result.

+

This function is thread-safe.

- interl_drv_getenv(const char *key, char *value, size_t *value_size) - Get the value of an environment variable + interl_drv_getenv(const char *key, char + *value, size_t *value_size) + Get the value of an environment variable. -

Arguments:

+

Retrieves the value of an environment variable.

key - A null terminated string containing the - name of the environment variable. + A NULL-terminated string containing the + name of the environment variable. value A pointer to an output buffer. value_size - A pointer to an integer. The integer is both used for - passing input and output sizes (see below). - + A pointer to an integer. The integer is used both for + passing input and output sizes (see below). -

This function retrieves the value of an environment variable. - When called, *value_size should contain the size of - the value buffer. On success 0 is returned, - the value of the environment variable has been written to - the value buffer, and *value_size contains the - string length (excluding the terminating null character) of - the value written to the value buffer. On failure, - i.e., no such environment variable was found, a value less than - 0 is returned. When the size of the value - buffer is too small, a value greater than 0 is returned - and *value_size has been set to the buffer size needed. -

-

Do not use libc's getenv or similar - C library interfaces from a driver. -

+

When this function is called, *value_size is to contain the + size of the value buffer.

+

On success, 0 is returned, + the value of the environment variable has been written to + the value buffer, and *value_size contains the + string length (excluding the terminating NULL character) of + the value written to the value buffer.

+

On failure, that is, no such environment variable was found, + a value < 0 is returned. When the size of the value + buffer is too small, a value > 0 is returned and + *value_size has been set to the buffer size needed.

+ +

Do not use libc's getenv or similar C library + interfaces from a driver.

+

This function is thread-safe.

- voiderl_drv_init_ack(ErlDrvPort port, ErlDrvData res) - Acknowledge the start of the port + voiderl_drv_init_ack(ErlDrvPort port, + ErlDrvData res) + Acknowledge the start of the port. -

Arguments:

+

Acknowledges the start of the port.

port - The port handle of the port (driver instance) creating - doing the acknowledgment. + The port handle of the port (driver instance) + doing the acknowledgment. res - The result of the port initialization. This can be the same values - as the return value of start, - i.e any of the error codes or the ErlDrvData that is to be used for this - port. + The result of the port initialization. Can be the same + values as the return value of + start, that is, any of the error codes or the + ErlDrvData that is to be used for this port. -

- When this function is called the initiating erlang:open_port call is - returned as if the start - function had just been called. It can only be used when the - ERL_DRV_FLAG_USE_INIT_ACK - flag has been set on the linked-in driver. -

-
-
- - - ErlDrvTimeerl_drv_monotonic_time(ErlDrvTimeUnit time_unit) - Get Erlang Monotonic Time - - -

Arguments:

- - time_unit - Time unit of returned value. - -

- Returns - Erlang - monotonic time. Note that it is not uncommon with - negative values. -

-

Returns ERL_DRV_TIME_ERROR if called with an invalid - time unit argument, or if called from a thread that is not a - scheduler thread.

-

See also:

- - ErlDrvTime - ErlDrvTimeUnit - -
-
- - - ErlDrvMutex *erl_drv_mutex_create(char *name) - Create a mutex +

When this function is called the initiating erlang:open_port + call is returned as if the + start function had just been called. It can only be + used when flag + ERL_DRV_FLAG_USE_INIT_ACK + has been set on the linked-in driver.

+ +
+ + + ErlDrvTime + erl_drv_monotonic_time(ErlDrvTimeUnit time_unit) + + Get Erlang monotonic time. + + +

Returns + Erlang monotonic time. Notice that negative values are + not uncommon.

+

time_unit is time unit of returned value.

+

Returns ERL_DRV_TIME_ERROR if called with an invalid + time unit argument, or if called from a thread that is not a + scheduler thread.

+

See also ErlDrvTime + and + ErlDrvTimeUnit.

+
+
+ + + ErlDrvMutex *erl_drv_mutex_create(char + *name) + Create a mutex. -

Arguments:

- - name - A string identifying the created mutex. It will be used - to identify the mutex in planned future debug functionality. - - -

This function creates a mutex and returns a pointer to it. On - failure NULL is returned. The driver creating the mutex - has the responsibility of destroying it before the driver is - unloaded. -

+

Creates a mutex and returns a pointer to it.

+

name is a string identifying the created mutex. It is used + to identify the mutex in planned future debug functionality.

+

Returns NULL on failure. The driver creating the mutex is + responsible for destroying it before the driver is unloaded.

This function is thread-safe.

- voiderl_drv_mutex_destroy(ErlDrvMutex *mtx) - Destroy a mutex + voiderl_drv_mutex_destroy(ErlDrvMutex + *mtx) + Destroy a mutex. -

Arguments:

- - mtx - A pointer to a mutex to destroy. - -

This function destroys a mutex previously created by - erl_drv_mutex_create(). - The mutex has to be in an unlocked state before being - destroyed. -

+

Destroys a mutex previously created by + + erl_drv_mutex_create. + The mutex must be in an unlocked state before it is destroyed.

+

mtx is a pointer to a mutex to destroy.

This function is thread-safe.

- voiderl_drv_mutex_lock(ErlDrvMutex *mtx) - Lock a mutex + voiderl_drv_mutex_lock(ErlDrvMutex + *mtx) + Lock a mutex. -

Arguments:

- - mtx - A pointer to a mutex to lock. - -

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 not lock - the same mutex again. -

-

If you leave a mutex locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Locks a mutex. The calling thread is blocked until the mutex has + been locked. A thread that has currently locked the mutex + cannot lock the same mutex again.

+

mtx is a pointer to a mutex to lock.

+ +

If you leave a mutex locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- - char *erl_drv_mutex_name(ErlDrvMutex *mtx) - Get name of driver mutex. - - -

Arguments:

- - mtx - A pointer to an initialized mutex. - -

- Returns a pointer to the name of the mutex. -

- -

This function is intended for debugging purposes only.

-
-
-
+ + char *erl_drv_mutex_name(ErlDrvMutex + *mtx) + Get name of driver mutex. + + +

Returns a pointer to the mutex name.

+

mtx is a pointer to an initialized mutex.

+ +

This function is intended for debugging purposes only.

+
+
+
- interl_drv_mutex_trylock(ErlDrvMutex *mtx) - Try lock a mutex + interl_drv_mutex_trylock(ErlDrvMutex + *mtx) + Try lock a mutex. -

Arguments:

- - mtx - A pointer to a mutex to try to lock. - -

This function tries to lock a mutex. If successful 0, - is returned; otherwise, EBUSY is returned. A thread - which currently has locked the mutex may not try to - lock the same mutex again. -

-

If you leave a mutex locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Tries to lock a mutex. A thred that has currently locked the mutex + cannot try to lock the same mutex again.

+

mtx is a pointer to a mutex to try to lock.

+

Returns 0 on success, otherwise EBUSY.

+ +

If you leave a mutex locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- voiderl_drv_mutex_unlock(ErlDrvMutex *mtx) - Unlock a mutex + voiderl_drv_mutex_unlock(ErlDrvMutex + *mtx) + Unlock a mutex. -

Arguments:

- - mtx - A pointer to a mutex to unlock. - -

This function unlocks a mutex. The mutex currently has to be - locked by the calling thread. -

+

Unlocks a mutex. The mutex currently must be + locked by the calling thread.

+

mtx is a pointer to a mutex to unlock.

This function is thread-safe.

- interl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n) - Send term data from driver to port owner + interl_drv_output_term(ErlDrvTermData port, + ErlDrvTermData* term, int n) + Send term data from driver to port owner. -

This functions sends data in the special driver term +

Sends data in the special driver term format to the port owner process. This is a fast way to - deliver term data from a driver. It also needs no binary - conversion, so the port owner process receives data as - normal Erlang terms. The - erl_drv_send_term() - functions can be used for sending to any arbitrary process - on the local node.

-

Note that the port parameter is not - an ordinary port handle, but a port handle converted using - driver_mk_port().

-

The term parameter points to an array of - ErlDrvTermData, with n elements. This array + deliver term data from a driver. It needs no binary + conversion, so the port owner process receives data as + normal Erlang terms. The + erl_drv_send_term + functions can be used for sending to any process + on the local node.

+ +

Parameter port is not + an ordinary port handle, but a port handle converted using + + driver_mk_port.

+
+

Parameter term points to an array of + ErlDrvTermData with n elements. This array contains terms described in the driver term format. Every - term consists of one to four elements in the array. The - term first has a term type, and then arguments. The - port parameter specifies the sending port.

-

Tuples, maps and lists (with the exception of strings, see below), + term consists of 1-4 elements in the array. The + first term has a term type and then arguments. + Parameter port specifies the sending port.

+

Tuples, maps, and lists (except strings, see below) are built in reverse polish notation, so that to build a - tuple, the elements are given first, and then the tuple + tuple, the elements are specified first, and then the tuple term, with a count. Likewise for lists and maps.

-

A tuple must be specified with the number of elements. (The - elements precede the ERL_DRV_TUPLE term.)

-

A list must be specified with the number of elements, - including the tail, which is the last term preceding - ERL_DRV_LIST.

-

A map must be specified with the number of key-value pairs N. - The key-value pairs must precede the ERL_DRV_MAP in this order: - key1,value1,key2,value2,...,keyN,valueN. - Duplicate keys are not allowed.

+ + +

A tuple must be specified with the number of elements. (The + elements precede the ERL_DRV_TUPLE term.)

+
+ +

A map must be specified with the number of key-value pairs + N. The key-value pairs must precede the ERL_DRV_MAP + in this order: key1,value1,key2,value2,...,keyN,valueN. + Duplicate keys are not allowed.

+
+ +

A list must be specified with the number of elements, + including the tail, which is the last term preceding + ERL_DRV_LIST.

+
+

The special term ERL_DRV_STRING_CONS 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 + "splice" in a string in a list, a string specified this way is + not a list in itself, but the elements are elements of the surrounding list.

-Term type            Argument(s)
-===========================================
+Term type            Arguments
+---------            ---------
 ERL_DRV_NIL
 ERL_DRV_ATOM         ErlDrvTermData atom (from driver_mk_atom(char *string))
 ERL_DRV_INT          ErlDrvSInt integer
@@ -2447,398 +2525,345 @@ 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_PID          ErlDrvTermData pid (from driver_connected(ErlDrvPort port)
+                     or driver_caller(ErlDrvPort port))
 ERL_DRV_STRING_CONS  char *str, int len
 ERL_DRV_FLOAT        double *dbl
 ERL_DRV_EXT2TERM     char *buf, ErlDrvUInt len
-ERL_DRV_MAP          int sz
-        
+ERL_DRV_MAP int sz

The unsigned integer data type ErlDrvUInt and the signed integer data type ErlDrvSInt 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 int arguments in the list above. -

+ on a 64-bit runtime system and 32 bits wide on a 32-bit + runtime system. They were introduced in ERTS 5.6 + and replaced some of the int arguments in the list above.

The unsigned integer data type ErlDrvUInt64 and the signed integer data type ErlDrvSInt64 are always 64 bits - wide. They were introduced in erts version 5.7.4. -

- -

To build the tuple {tcp, Port, [100 | Binary]}, the - following call could be made.

- - -

Where bin is a driver binary of length at least 50 - and drvport is a port handle. Note that the ERL_DRV_LIST - comes after the elements of the list, likewise the + wide. They were introduced in ERTS 5.7.4.

+

To build the tuple {tcp, Port, [100 | Binary]}, the + following call can be made.

+ +

Here bin is a driver binary of length at least 50 and + drvport is a port handle. Notice that ERL_DRV_LIST + comes after the elements of the list, likewise ERL_DRV_TUPLE.

-

The term ERL_DRV_STRING_CONS is a way to construct +

The ERL_DRV_STRING_CONS term is a way to construct strings. It works differently from how ERL_DRV_STRING works. ERL_DRV_STRING_CONS builds a string list in - reverse order, (as opposed to how ERL_DRV_LIST + reverse order (as opposed to how ERL_DRV_LIST works), concatenating the strings added to a list. The tail - must be given before ERL_DRV_STRING_CONS.

-

The ERL_DRV_STRING constructs a string, and ends - it. (So it's the same as ERL_DRV_NIL followed by + must be specifed before ERL_DRV_STRING_CONS.

+

ERL_DRV_STRING constructs a string, and ends + it. (So it is the same as ERL_DRV_NIL followed by ERL_DRV_STRING_CONS.)

-

+/* to send [x, "abc", y] to the port: */ +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("x"), + ERL_DRV_STRING, (ErlDrvTermData)"abc", 3, + ERL_DRV_ATOM, driver_mk_atom("y"), + ERL_DRV_NIL, + ERL_DRV_LIST, 4 +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]> +/* to send "abc123" to the port: */ +ErlDrvTermData spec[] = { + ERL_DRV_NIL, /* with STRING_CONS, the tail comes first */ + ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3, + ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]>

The ERL_DRV_EXT2TERM term type is used for passing a - term encoded with the - external format, - i.e., a term that has been encoded by - erlang:term_to_binary, - erl_interface, etc. - For example, if binp is a pointer to an ErlDrvBinary - that contains the term {17, 4711} encoded with the - external format - and you want to wrap it in a two tuple with the tag my_tag, - i.e., {my_tag, {17, 4711}}, you can do as follows: -

- orig_bytes, binp->orig_size - ERL_DRV_TUPLE, 2, - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]> - + term encoded with the + external format, + that is, a term that has been encoded by + + erlang:term_to_binary, + erl_interface, + and so on. + For example, if binp is a pointer to an ErlDrvBinary + that contains term {17, 4711} encoded with the + external format, + and you want to wrap it in a two-tuple with the tag my_tag, + that is, {my_tag, {17, 4711}}, you can do as follows:

+ orig_bytes, binp->orig_size + ERL_DRV_TUPLE, 2, +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]>

To build the map #{key1 => 100, key2 => {200, 300}}, the - following call could be made.

+ following call can be made.

- - -

If you want to pass a binary and don't already have the content - of the binary in an ErlDrvBinary, you can benefit from using - ERL_DRV_BUF2BINARY instead of creating an ErlDrvBinary - via driver_alloc_binary() and then pass the binary via - ERL_DRV_BINARY. The runtime system will often allocate - binaries smarter if ERL_DRV_BUF2BINARY is used. - However, if the content of the binary to pass already resides in - an ErlDrvBinary, it is normally better to pass the binary - using ERL_DRV_BINARY and the ErlDrvBinary in question. -

-

The ERL_DRV_UINT, ERL_DRV_BUF2BINARY, and - ERL_DRV_EXT2TERM term types were introduced in the 5.6 - version of erts. -

+ErlDrvPort port = ... +ErlDrvTermData spec[] = { + ERL_DRV_ATOM, driver_mk_atom("key1"), + ERL_DRV_INT, 100, + ERL_DRV_ATOM, driver_mk_atom("key2"), + ERL_DRV_INT, 200, + ERL_DRV_INT, 300, + ERL_DRV_TUPLE, 2, + ERL_DRV_MAP, 2 +}; +erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]> +

If you want to pass a binary and do not already have the content + of the binary in an ErlDrvBinary, you can benefit from using + ERL_DRV_BUF2BINARY instead of creating an ErlDrvBinary + through + driver_alloc_binary and then pass the binary through + ERL_DRV_BINARY. The runtime system often allocates + binaries smarter if ERL_DRV_BUF2BINARY is used. + However, if the content of the binary to pass already resides in + an ErlDrvBinary, it is normally better to pass the binary using + ERL_DRV_BINARY and the ErlDrvBinary in question.

+

The ERL_DRV_UINT, ERL_DRV_BUF2BINARY, and + ERL_DRV_EXT2TERM term types were introduced in + ERTS 5.6.

This function is only thread-safe when the emulator with SMP support is used.

- interl_drv_putenv(const char *key, char *value) - Set the value of an environment variable + interl_drv_putenv(const char *key, char + *value) + Set the value of an environment variable. -

Arguments:

- - key - A null terminated string containing the - name of the environment variable. - value - A null terminated string containing the - new value of the environment variable. - -

This function sets the value of an environment variable. - It returns 0 on success, and a value != 0 on - failure. -

-

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.

-
-

Do not use libc's putenv or similar - C library interfaces from a driver. -

+

Sets the value of an environment variable.

+

key is a NULL-terminated string containing the + name of the environment variable.

+

value is a NULL-terminated string containing the + new value of the environment variable.

+

Returns 0 on success, otherwise a value != 0.

+ +

The result of passing the empty string ("") as a value + is platform-dependent. On some platforms the variable value + is set to the empty string, on others the + environment variable is removed.

+
+ +

Do not use libc's putenv or similar C library + interfaces from a driver.

+

This function is thread-safe.

- ErlDrvRWLock *erl_drv_rwlock_create(char *name) - Create an rwlock + ErlDrvRWLock *erl_drv_rwlock_create(char + *name) + Create an rwlock. -

Arguments:

- - name - A string identifying the created rwlock. It will be used to - identify the rwlock in planned future debug functionality. - - -

This function creates an rwlock and returns a pointer to it. On - failure NULL is returned. The driver creating the rwlock - has the responsibility of destroying it before the driver is - unloaded. -

+

Creates an rwlock and returns a pointer to it.

+

name is a string identifying the created rwlock. + It is used to identify the rwlock in planned future + debug functionality.

+

Returns NULL on failure. The driver creating the rwlock + is responsible for destroying it before the driver is unloaded.

This function is thread-safe.

- voiderl_drv_rwlock_destroy(ErlDrvRWLock *rwlck) - Destroy an rwlock + voiderl_drv_rwlock_destroy(ErlDrvRWLock + *rwlck) + Destroy an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to destroy. - -

This function destroys an rwlock previously created by - erl_drv_rwlock_create(). - The rwlock has to be in an unlocked state before being destroyed. -

+

Destroys an rwlock previously created by + + erl_drv_rwlock_create. + The rwlock must be in an unlocked state before it is destroyed.

+

rwlck is a pointer to an rwlock to destroy.

This function is thread-safe.

- - char *erl_drv_rwlock_name(ErlDrvRWLock *rwlck) - Get name of driver mutex. - - -

Arguments:

- - rwlck - A pointer to an initialized r/w-lock. - -

- Returns a pointer to the name of the r/w-lock. -

- -

This function is intended for debugging purposes only.

-
-
-
+ + char *erl_drv_rwlock_name(ErlDrvRWLock + *rwlck) + Get name of driver mutex. + + +

Returns a pointer to the name of the rwlock.

+

rwlck is a pointer to an initialized rwlock.

+ +

This function is intended for debugging purposes only.

+
+
+
- voiderl_drv_rwlock_rlock(ErlDrvRWLock *rwlck) - Read lock an rwlock + voiderl_drv_rwlock_rlock(ErlDrvRWLock + *rwlck) + Read lock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to read lock. - -

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 - not lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Read locks an rwlock. The calling thread is + blocked until the rwlock has been read locked. A thread + that currently has read or read/write locked the rwlock + cannot lock the same rwlock again.

+

rwlck is a pointer to the rwlock to read lock.

+ +

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- voiderl_drv_rwlock_runlock(ErlDrvRWLock *rwlck) - Read unlock an rwlock + voiderl_drv_rwlock_runlock(ErlDrvRWLock + *rwlck) + Read unlock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to read unlock. - -

This function read unlocks an rwlock. The rwlock currently - has to be read locked by the calling thread. -

+

Read unlocks an rwlock. The rwlock currently must + be read locked by the calling thread.

+

rwlck is a pointer to an rwlock to read unlock.

This function is thread-safe.

- voiderl_drv_rwlock_rwlock(ErlDrvRWLock *rwlck) - Read/Write lock an rwlock + voiderl_drv_rwlock_rwlock(ErlDrvRWLock + *rwlck) + Read/write lock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to read/write lock. - -

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 not lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Read/write locks an rwlock. The calling thread + is blocked until the rwlock has been read/write locked. + A thread that currently has read or read/write locked the + rwlock cannot lock the same rwlock again.

+

rwlck is a pointer to an rwlock to read/write lock.

+ +

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- voiderl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck) - Read/Write unlock an rwlock + voiderl_drv_rwlock_rwunlock(ErlDrvRWLock + *rwlck) + Read/write unlock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to read/write unlock. - -

This function read/write unlocks an rwlock. The rwlock - currently has to be read/write locked by the calling thread. -

+

Read/write unlocks an rwlock. The rwlock currently must be + read/write locked by the calling thread.

+

rwlck is a pointer to an rwlock to read/write unlock.

This function is thread-safe.

- interl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck) - Try to read lock an rwlock + interl_drv_rwlock_tryrlock(ErlDrvRWLock + *rwlck) + Try to read lock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to try to read lock. - -

This function tries to read lock an rwlock. If successful - 0, is returned; otherwise, EBUSY is returned. - A thread which currently has read or read/write locked the - rwlock may not try to lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Tries to read lock an rwlock.

+

rwlck is a pointer to an rwlock to try to read lock.

+

Returns 0 on success, otherwise EBUSY. + A thread that currently has read or read/write locked the + rwlock cannot try to lock the same rwlock again.

+ +

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- interl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck) - Try to read/write lock an rwlock + interl_drv_rwlock_tryrwlock(ErlDrvRWLock + *rwlck) + Try to read/write lock an rwlock. -

Arguments:

- - rwlck - A pointer to an rwlock to try to read/write lock. - -

This function tries to read/write lock an rwlock. If successful - 0, is returned; otherwise, EBUSY is returned. - A thread which currently has read or read/write locked the - rwlock may not try to lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

+

Tries to read/write lock an rwlock. + A thread that currently has read or read/write locked the + rwlock cannot try to lock the same rwlock again.

+

rwlckis pointer to an rwlock to try to read/write lock.

+

Returns 0 om success, otherwise EBUSY.

+ +

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

+

This function is thread-safe.

- interl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) - Send term data to other process than port owner process + interl_drv_send_term(ErlDrvTermData port, + ErlDrvTermData receiver, ErlDrvTermData* term, int n) + Send term data to other process than port owner process. +

This function is the only way for a driver to send data to - other processes than the port owner process. The - receiver parameter specifies the process to receive - the data.

-

Note that the port parameter is not - an ordinary port handle, but a port handle converted using - driver_mk_port().

-

The parameters port, term and n do the same thing - as in erl_drv_output_term().

+ other processes than the port owner process. Parameter + receiver specifies the process to receive the data.

+ +

Parameter port is not an ordinary port handle, but + a port handle converted using + + driver_mk_port.

+
+

Parameters port, term, and n work as in + + erl_drv_output_term.

This function is only thread-safe when the emulator with SMP support is used.

- voiderl_drv_set_os_pid(ErlDrvPort port, ErlDrvSInt pid) - Set the os_pid for the port + voiderl_drv_set_os_pid(ErlDrvPort port, + ErlDrvSInt pid) + Set the os_pid for the port. -

Arguments:

- - port - The port handle of the port (driver instance) to set the pid on. - - pid - The pid to set. - -

- Set the os_pid seen when doing erlang:port_info/2 on this port. -

+

Sets the os_pid seen when doing + + erlang:port_info/2 on this port.

+

port is the port handle of the port (driver instance) to set + the pid on. pidis the pid to set.

- interl_drv_thread_create(char *name, - ErlDrvTid *tid, - void * (*func)(void *), - void *arg, - ErlDrvThreadOpts *opts) - Create a thread + interl_drv_thread_create(char *name, ErlDrvTid + *tid, void * (*func)(void *), void *arg, ErlDrvThreadOpts + *opts) + Create a thread. -

Arguments:

+

Creates a new thread.

name - A string identifying the created thread. It will be used - to identify the thread in planned future debug - functionality. - + A string identifying the created thread. It is used to + identify the thread in planned future debug functionality. + tid A pointer to a thread identifier variable. func @@ -2848,377 +2873,348 @@ ERL_DRV_MAP int sz opts A pointer to thread options to use or NULL. -

This function creates a new thread. On success 0 is returned; - otherwise, an errno value is returned to indicate the error. - The newly created thread will begin executing in the function pointed - to by func, and func will be passed arg as - argument. When erl_drv_thread_create() returns the thread - identifier of the newly created thread will be available in - *tid. opts can be either a NULL pointer, or a - pointer to an - ErlDrvThreadOpts - structure. If opts is a NULL pointer, default options - will be used; otherwise, the passed options will be used. -

-

You are not allowed to allocate the - ErlDrvThreadOpts - structure by yourself. It has to be allocated and - initialized by - erl_drv_thread_opts_create(). -

-

The created thread will terminate either when func returns - or if - erl_drv_thread_exit() - is called by the thread. The exit value of the thread is either - returned from func or passed as argument to - erl_drv_thread_exit(). - The driver creating the thread has the responsibility of joining the - thread, via - erl_drv_thread_join(), - before the driver is unloaded. It is not possible to create - "detached" threads, i.e., threads that don't need to be joined. -

-

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. -

+

Returns 0 on success, + otherwise an errno value is returned to indicate the error. + The newly created thread begins executing in the function pointed + to by func, and func is passed arg as + argument. When erl_drv_thread_create returns, the thread + identifier of the newly created thread is available in + *tid. opts can be either a NULL pointer, or a + pointer to an + ErlDrvThreadOpts + structure. If opts is a NULL pointer, default options + are used, otherwise the passed options are used.

+ +

You are not allowed to allocate the + + ErlDrvThreadOpts structure by yourself. + It must be allocated and initialized by + + erl_drv_thread_opts_create.

+
+

The created thread terminates either when func returns or if + + erl_drv_thread_exit + is called by the thread. The exit value of the thread is either + returned from func or passed as argument to + + erl_drv_thread_exit. + The driver creating the thread is responsible for joining the + thread, through + erl_drv_thread_join, + before the driver is unloaded. "Detached" threads cannot be created, + that is, threads that do not need to be joined.

+ +

All created threads must be joined by the driver before + it is unloaded. If the driver fails to join all threads + created before it is unloaded, the runtime system + most likely crashes when the driver code is unloaded.

+

This function is thread-safe.

- voiderl_drv_thread_exit(void *exit_value) - Terminate calling thread + voiderl_drv_thread_exit(void + *exit_value) + Terminate calling thread. -

Arguments:

- - exit_value - A pointer to an exit value or NULL. - -

This function terminates the calling thread with the exit - value passed as argument. You are only allowed to terminate - threads created with - erl_drv_thread_create(). - The exit value can later be retrieved by another thread via - erl_drv_thread_join(). -

+

Terminates the calling thread with the exit value passed as + argument. exit_value is a pointer to an exit value or + NULL.

+

You are only allowed to terminate threads created with + + erl_drv_thread_create.

+

The exit value can later be retrieved by another thread through + + erl_drv_thread_join.

This function is thread-safe.

- interl_drv_thread_join(ErlDrvTid tid, void **exit_value) - Join with another thread + interl_drv_thread_join(ErlDrvTid tid, void + **exit_value) + Join with another thread. -

Arguments:

- - tid - The thread identifier of the thread to join. - exit_value - A pointer to a pointer to an exit value, or NULL. - -

This function joins the calling thread with another thread, i.e., - the calling thread is blocked until the thread identified by - tid has terminated. On success 0 is returned; - otherwise, an errno 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 - exit_value == NULL, the exit value of the terminated thread - will be ignored; otherwise, the exit value of the terminated thread - will be stored at *exit_value. -

+

Joins the calling thread with another thread, that is, + the calling thread is blocked until the thread identified by + tid has terminated.

+

tid is the thread identifier of the thread to join. + exit_value is a pointer to a pointer to an exit value, + or NULL.

+

Returns 0 on success, otherwise an errno + 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 + exit_value == NULL, the exit value of the terminated thread + is ignored, otherwise the exit value of the terminated thread + is stored at *exit_value.

This function is thread-safe.

- - char *erl_drv_thread_name(ErlDrvTid tid) - Get name of driver mutex. - - -

Arguments:

- - tid - A thread identifier. - -

- Returns a pointer to the name of the thread. -

- -

This function is intended for debugging purposes only.

-
-
-
+ + char *erl_drv_thread_name(ErlDrvTid + tid) + Get name of driver mutex. + + +

Returns a pointer to the name of the thread.

+

tid is a thread identifier.

+ +

This function is intended for debugging purposes only.

+
+
+
- ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name) - Create thread options + ErlDrvThreadOpts * + erl_drv_thread_opts_create(char *name) + Create thread options. -

Arguments:

- - name - A string identifying the created thread options. It will be used - to identify the thread options in planned future debug - functionality. - - -

This function allocates and initialize a thread option - structure. On failure NULL is returned. A thread option - structure is used for passing options to - erl_drv_thread_create(). - If the structure isn't modified before it is passed to - erl_drv_thread_create(), - the default values will be used. -

-

You are not allowed to allocate the - ErlDrvThreadOpts - structure by yourself. It has to be allocated and - initialized by erl_drv_thread_opts_create(). -

+

Allocates and initializes a thread option structure.

+

name is a string identifying the created thread options. + It is used to identify the thread options in planned future debug + functionality.

+

Returns NULL on failure. A thread option + structure is used for passing options to + + erl_drv_thread_create. + If the structure is not modified before it is passed to + + erl_drv_thread_create, + the default values are used.

+ +

You are not allowed to allocate the + + ErlDrvThreadOpts + structure by yourself. It must be allocated and initialized by + erl_drv_thread_opts_create.

+

This function is thread-safe.

- voiderl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts) - Destroy thread options + void + erl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts) + + Destroy thread options. -

Arguments:

- - opts - A pointer to thread options to destroy. - -

This function destroys thread options previously created by - erl_drv_thread_opts_create(). -

+

Destroys thread options previously created by + + erl_drv_thread_opts_create.

+

opts is a pointer to thread options to destroy.

This function is thread-safe.

- ErlDrvTiderl_drv_thread_self(void) - Get the thread identifier of the current thread + ErlDrvTid + erl_drv_thread_self(void) + Get the thread identifier of the current thread. -

This function returns the thread identifier of the - calling thread. -

+

Returns the thread identifier of the calling thread.

This function is thread-safe.

- - ErlDrvTimeerl_drv_time_offset(ErlDrvTimeUnit time_unit) - Get current Time Offset - - -

Arguments:

- - time_unit - Time unit of returned value. - -

Returns the current time offset between - Erlang monotonic time - and - Erlang system time - converted into the time_unit passed as argument.

-

Returns ERL_DRV_TIME_ERROR if called with an invalid - time unit argument, or if called from a thread that is not a - scheduler thread.

-

See also:

- - ErlDrvTime - ErlDrvTimeUnit - -
-
- - - void *erl_drv_tsd_get(ErlDrvTSDKey key) - Get thread specific data + + ErlDrvTimeerl_drv_time_offset(ErlDrvTimeUnit + time_unit) + Get current time offset. + + +

Returns the current time offset between + + Erlang monotonic time and + + Erlang system time + converted into the time_unit passed as argument.

+

time_unit is time unit of returned value.

+

Returns ERL_DRV_TIME_ERROR if called with an invalid + time unit argument, or if called from a thread that is not a + scheduler thread.

+

See also + ErlDrvTime and + + ErlDrvTimeUnit.

+
+
+ + + void *erl_drv_tsd_get(ErlDrvTSDKey + key) + Get thread-specific data. -

Arguments:

- - key - A thread specific data key. - -

This function returns the thread specific data - associated with key for the calling thread. - If no data has been associated with key for - the calling thread, NULL is returned. -

+

Returns the thread-specific data + associated with key for the calling thread.

+

key is a thread-specific data key.

+

Returns NULL if no data has been associated + with key for the calling thread.

This function is thread-safe.

- interl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key) - Create a thread specific data key + interl_drv_tsd_key_create(char *name, + ErlDrvTSDKey *key) + Create a thread-specific data key. -

Arguments:

- - name - A string identifying the created key. It will be used - to identify the key in planned future debug - functionality. - - key - A pointer to a thread specific data key variable. - -

This function creates a thread specific data key. On success - 0 is returned; otherwise, an errno value is returned - to indicate the error. The driver creating the key has the - responsibility of destroying it before the driver is unloaded. -

+

Creates a thread-specific data key.

+

name is a string identifying the created key. It is used + to identify the key in planned future debug functionality.

+

key is a pointer to a thread-specific data key variable.

+

Returns 0 on success, otherwise an errno value is + returned to indicate the error. The driver creating the key is + responsible for destroying it before the driver is unloaded.

This function is thread-safe.

- voiderl_drv_tsd_key_destroy(ErlDrvTSDKey key) - Destroy a thread specific data key + voiderl_drv_tsd_key_destroy(ErlDrvTSDKey + key) + Destroy a thread-specific data key. -

Arguments:

- - key - A thread specific data key to destroy. - -

This function destroys a thread specific data key - previously created by - erl_drv_tsd_key_create(). - All thread specific data using this key in all threads - have to be cleared (see - erl_drv_tsd_set()) - prior to the call to erl_drv_tsd_key_destroy(). -

-

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 very likely get unexpected - errors in other parts of the system. -

+

Destroys a thread-specific data key previously created by + + erl_drv_tsd_key_create. + All thread-specific data using this key in all threads + must be cleared (see + erl_drv_tsd_set) + before the call to erl_drv_tsd_key_destroy.

+

key is a thread-specific data key to destroy.

+ +

A destroyed key is very likely to be reused soon. + Therefore, if you fail to clear the thread-specific + data using this key in a thread before destroying + the key, you will very likely get unexpected + errors in other parts of the system.

+

This function is thread-safe.

- voiderl_drv_tsd_set(ErlDrvTSDKey key, void *data) - Set thread specific data + voiderl_drv_tsd_set(ErlDrvTSDKey key, void + *data) + Set thread-specific data. -

Arguments:

- - key - A thread specific data key. - data - A pointer to data to associate with key - in calling thread. - - -

This function sets thread specific data associated with - key 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 NULL, before returning from the driver call-back - function. -

-

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. -

+

Sets thread-specific data associated with + key for the calling thread. You are only allowed to set + thread-specific data for threads while they are fully under your + control. For example, if you set thread-specific data in a thread + calling a driver callback function, it must be cleared, that is, + set to NULL, before returning from the driver callback + function.

+

key is a thread-specific data key.

+

data is a pointer to data to associate with key + in the calling thread.

+ +

If you fail to clear thread-specific data in an + emulator thread before letting it out of your control, + you might never be able to clear this data with + later unexpected errors in other parts of the system as + a result.

+

This function is thread-safe.

char *erl_errno_id(int error) - Get erlang error atom name from error number + Get Erlang error atom name from error number. -

This function returns the atom name of the erlang error, - given the error number in error. Error atoms are: - einval, enoent, etc. It can be used to make +

Returns the atom name of the Erlang error, + given the error number in error. The error atoms are + einval, enoent, and so on. It can be used to make error terms from the driver.

- intremove_driver_entry(ErlDrvEntry *de) - Remove a driver entry + intremove_driver_entry(ErlDrvEntry + *de) + Remove a driver entry. -

This function removes a driver entry de previously - added with add_driver_entry.

-

Driver entries added by the erl_ddll erlang interface can - not be removed by using this interface.

+

Removes a driver entry de previously added with + + add_driver_entry.

+

Driver entries added by the erl_ddll Erlang interface + cannot be removed by using this interface.

- voidset_busy_port(ErlDrvPort port, int on) - Signal or unsignal port as busy + voidset_busy_port(ErlDrvPort port, int + on) + Signal or unsignal port as busy. -

This function set and unset the busy state of the port. If - on is non-zero, the port is set to busy, if it's zero the port - is set to not busy. You typically want to combine - this feature with the busy - port message queue functionality.

-

Processes sending command data to the port will be suspended - if either the port is busy or if the port message queue - is busy. Suspended processes will be resumed when neither the - port is busy, nor the port message queue is busy. Command data - is in this context data passed to the port using either - Port ! {Owner, {command, Data}}, or - port_command/[2,3].

-

If the - - has been set in the - driver_entry, - data can be forced into the driver via - port_command(Port, Data, [force]) - even though the driver has signaled that it is busy. -

-

For information about busy port message queue functionality - see the documentation of the - erl_drv_busy_msgq_limits() - function.

-
-
- - - voidset_port_control_flags(ErlDrvPort port, int flags) - Set flags on how to handle control entry function +

Sets and unsets the busy state of the port. If + on is non-zero, the port is set to busy. If it is zero, + the port is set to not busy. You typically want to combine + this feature with the + busy port message queue functionality.

+

Processes sending command data to the port are suspended + if either the port or the port message queue + is busy. Suspended processes are resumed when neither the + port or the port message queue is busy. Command data + is in this context data passed to the port using either + Port ! {Owner, {command, Data}} or + port_command/[2,3].

+

If the + has been set in the + driver_entry, + data can be forced into the driver through + + erlang:port_command(Port, Data, [force]) + even if the driver has signaled that it is busy.

+

For information about busy port message queue functionality, see + + erl_drv_busy_msgq_limits.

+ +
+ + + voidset_port_control_flags(ErlDrvPort port, + int flags) + Set flags on how to handle control entry function. -

This function sets flags for how the control driver entry - function will return data to the port owner process. (The - control function is called from port_control/3 - in erlang.)

+

Sets flags for how the + control driver entry + function will return data to the port owner process. + (The control function is called from + + erlang:port_control/3.)

Currently there are only two meaningful values for - flags: 0 means that data is returned in a list, and - PORT_CONTROL_FLAG_BINARY means data is returned as + flags: 0 means that data is returned in a list, + and PORT_CONTROL_FLAG_BINARY means data is returned as a binary from control.

+
- SEE ALSO -

driver_entry(3), - erl_ddll(3), - erlang(3)

-

An Alternative Distribution Driver (ERTS User's - Guide Ch. 3)

+ See Also +

driver_entry(3), + erlang(3), + kernel:erl_ddll(3), + section How to Implement an Alternative + Carrier for the Erlang Distribution> in the User's Guide

diff --git a/erts/doc/src/erl_ext_dist.xml b/erts/doc/src/erl_ext_dist.xml index 2ac974f497..2ff0f39a3f 100644 --- a/erts/doc/src/erl_ext_dist.xml +++ b/erts/doc/src/erl_ext_dist.xml @@ -35,135 +35,130 @@
Introduction

- The external term format is mainly used in the distribution + The external term format is mainly used in the distribution mechanism of Erlang.

- Since Erlang has a fixed number of types, there is no need for a - programmer to define a specification for the external format used + As Erlang has a fixed number of types, there is no need for a + programmer to define a specification for the external format used within some application. - All Erlang terms has an external representation and the interpretation - of the different terms are application specific. + All Erlang terms have an external representation and the interpretation + of the different terms is application-specific.

- In Erlang the BIF term_to_binary/1,2 is used to convert a - term into the external format. - To convert binary data encoding a term the BIF + In Erlang the BIF + erlang:term_to_binary/1,2 is used to convert a + term into the external format. + To convert binary data encoding to a term, the BIF - binary_to_term/1 - - is used. + erlang:binary_to_term/1c> is used.

- The distribution does this implicitly when sending messages across + The distribution does this implicitly when sending messages across node boundaries.

- The overall format of the term format is: + The overall format of the term format is as follows:

- 1 - 1 - N + 1 + 1 + N - - 131 - Tag - Data - -
+ + 131 + Tag + Data + + Term Format -

- When messages are - passed between - connected nodes and a - distribution - header 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. -

+

+ When messages are + passed between + connected nodes and a + distribution + header is used, the first byte containing the version + number (131) is omitted from the terms that follow the distribution + header. This is because the version number is implied by the version + number in the distribution header. +

- A compressed term looks like this: + The compressed term format is as follows:

- 1 - 1 - 4 - N + 1 + 1 + 4 + N - 131 - 80 - UncompressedSize - Zlib-compressedData + 131 + 80 + UncompressedSize + Zlib-compressedData -
+ Compressed Term Format

- Uncompressed Size (unsigned 32 bit integer in big-endian byte order) + Uncompressed size (unsigned 32-bit integer in big-endian byte order) is the size of the data before it was compressed. - The compressed data has the following format when it has been - expanded: + The compressed data has the following format when it has been expanded:

- 1 - Uncompressed Size + 1 + Uncompressed Size - Tag - Data + Tag + Data -
+ Compressed Data Format when Expanded -

As of ERTS version 5.10 (OTP-R16) support - for UTF-8 encoded atoms has been introduced in the external format. - However, only characters that can be encoded using Latin1 (ISO-8859-1) - are currently supported in atoms. The support for UTF-8 encoded atoms - in the external format has been implemented in order to be able to support - all Unicode characters in atoms in some future release. - Until full Unicode support for - atoms has been introduced, it is an error to pass atoms containing - characters that cannot be encoded in Latin1, and the behavior is - undefined.

-

When the - DFLAG_UTF8_ATOMS - distribution flag has been exchanged between both nodes in the - distribution handshake, - all atoms in the distribution header will be encoded in UTF-8; otherwise, - all atoms in the distribution header will be encoded in Latin1. The two - new tags ATOM_UTF8_EXT, and - SMALL_ATOM_UTF8_EXT - will only be used if the DFLAG_UTF8_ATOMS distribution flag has - been exchanged between nodes, or if an atom containing characters - that cannot be encoded in Latin1 is encountered. -

-

The maximum number of allowed characters in an atom is 255. In the - UTF-8 case each character may need 4 bytes to be encoded. -

+

As from ERTS 5.10 (OTP R16) support + for UTF-8 encoded atoms has been introduced in the external format. + However, only characters that can be encoded using Latin-1 (ISO-8859-1) + are currently supported in atoms. The support for UTF-8 encoded atoms + in the external format has been implemented to be able to support + all Unicode characters in atoms in some future release. + Until full Unicode support for atoms has been introduced, + it is an error to pass atoms containing + characters that cannot be encoded in Latin-1, and the behavior is + undefined.

+

When distribution flag + DFLAG_UTF8_ATOMS has been exchanged between both nodes + in th + distribution handshake, all atoms in the distribution header + are encoded in UTF-8, otherwise in Latin-1. The two + new tags ATOM_UTF8_EXT + and + SMALL_ATOM_UTF8_EXT + are only used if the distribution flag DFLAG_UTF8_ATOMS has + been exchanged between nodes, or if an atom containing characters + that cannot be encoded in Latin-1 is encountered.

+

The maximum number of allowed characters in an atom is 255. In the + UTF-8 case, each character can need 4 bytes to be encoded.

- Distribution header + Distribution Header

- 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 + As from ERTS 5.7.2 the old atom cache protocol was + dropped and a new one was introduced. This protocol + introduced the distribution header. Nodes with an ERTS version earlier than 5.7.2 can still communicate with new nodes, - but no distribution header and no atom cache will be used.

+ but no distribution header and no atom cache are used.

- The distribution header currently only contains an atom cache - reference section, but could in the future contain more + The distribution header only contains an atom cache + reference section, but can in the future contain more information. The distribution header precedes one or more Erlang - terms on the external format. For more information see the + terms on the external format. For more information, see the documentation of the protocol between connected nodes in the @@ -173,37 +168,37 @@

ATOM_CACHE_REF entries with corresponding AtomCacheReferenceIndex in terms - encoded on the external format following a distribution header refers + encoded on the external format following a distribution header refer to the atom cache references made in the distribution header. The range - is 0 <= AtomCacheReferenceIndex < 255, i.e., at most 255 + is 0 <= AtomCacheReferenceIndex < 255, that is, at most 255 different atom cache references from the following terms can be made.

- The distribution header format is: + The distribution header format is as follows:

- 1 - 1 - 1 - NumberOfAtomCacheRefs/2+1 | 0 - N | 0 + 1 + 1 + 1 + NumberOfAtomCacheRefs/2+1 | 0 + N | 0 - 131 - 68 - NumberOfAtomCacheRefs - Flags - AtomCacheRefs + 131 + 68 + NumberOfAtomCacheRefs + Flags + AtomCacheRefs -
+ Distribution Header Format

- Flags consists of NumberOfAtomCacheRefs/2+1 bytes, + Flags consist of NumberOfAtomCacheRefs/2+1 bytes, unless NumberOfAtomCacheRefs is 0. If NumberOfAtomCacheRefs is 0, Flags and - AtomCacheRefs are omitted. Each atom cache reference have + AtomCacheRefs are omitted. Each atom cache reference has a half byte flag field. Flags corresponding to a specific - AtomCacheReferenceIndex, are located in flag byte number + AtomCacheReferenceIndex are located in flag byte number AtomCacheReferenceIndex/2. Flag byte 0 is the first byte after the NumberOfAtomCacheRefs byte. Flags for an even AtomCacheReferenceIndex are located in the least significant @@ -216,95 +211,97 @@

- 1 bit - 3 bits + 1 bit + 3 bits - NewCacheEntryFlag - SegmentIndex + NewCacheEntryFlag + SegmentIndex

The most significant bit is the NewCacheEntryFlag. If set, the corresponding cache reference is new. The three least significant bits are the SegmentIndex of the corresponding - atom cache entry. An atom cache consists of 8 segments each of size - 256, i.e., an atom cache can contain 2048 entries. + atom cache entry. An atom cache consists of 8 segments, each of size + 256, that is, an atom cache can contain 2048 entries.

After flag fields for atom cache references, another half byte flag - field is located which has the following format: + field is located with the following format:

- 3 bits - 1 bit + 3 bits + 1 bit - CurrentlyUnused - LongAtoms + CurrentlyUnused + LongAtoms

- The least significant bit in that half byte is the LongAtoms - flag. If it is set, 2 bytes are used for atom lengths instead of + The least significant bit in that half byte is flag LongAtoms. + If it is set, 2 bytes are used for atom lengths instead of 1 byte in the distribution header.

After the Flags field follow the AtomCacheRefs. The first AtomCacheRef is the one corresponding to - AtomCacheReferenceIndex 0. Higher indices follows + AtomCacheReferenceIndex 0. Higher indices follow in sequence up to index NumberOfAtomCacheRefs - 1.

If the NewCacheEntryFlag for the next AtomCacheRef has - been set, a NewAtomCacheRef on the following format will follow: + been set, a NewAtomCacheRef on the following format follows:

- 1 - 1 | 2 - Length + 1 + 1 | 2 + Length - InternalSegmentIndex - Length - AtomText + InternalSegmentIndex + Length + AtomText

InternalSegmentIndex together with the SegmentIndex completely identify the location of an atom cache entry in the - atom cache. Length is number of bytes that AtomText - consists of. Length is a two byte big endian integer - if the LongAtoms flag has been set, otherwise a one byte - integer. When the - DFLAG_UTF8_ATOMS - distribution flag has been exchanged between both nodes in the - distribution handshake, - characters in AtomText is encoded in UTF-8; otherwise, - encoded in Latin1. Subsequent CachedAtomRefs with the same + atom cache. Length is the number of bytes that AtomText + consists of. Length is a 2 byte big-endian integer + if flag LongAtoms has been set, otherwise a 1 byte + integer. When distribution flag + + DFLAG_UTF8_ATOMS + has been exchanged between both nodes in the + + distribution handshake, + characters in AtomText are encoded in UTF-8, otherwise + in Latin-1. The following CachedAtomRefs with the same SegmentIndex and InternalSegmentIndex as this - NewAtomCacheRef will refer to this atom until a new + NewAtomCacheRef refer to this atom until a new NewAtomCacheRef with the same SegmentIndex and InternalSegmentIndex appear.

- For more information on encoding of atoms, see + For more information on encoding of atoms, see the note on UTF-8 encoded atoms - in the beginning of this document. + in the beginning of this section.

If the NewCacheEntryFlag for the next AtomCacheRef has not been set, a CachedAtomRef on the following format - will follow: + follows:

- 1 + 1 - InternalSegmentIndex + InternalSegmentIndex

@@ -319,157 +316,147 @@

ATOM_CACHE_REF - 1 - 1 + 1 - 82 - AtomCacheReferenceIndex + 82 + AtomCacheReferenceIndex -
+ ATOM_CACHE_REF

Refers to the atom with AtomCacheReferenceIndex in the - distribution header. + distribution header.

SMALL_INTEGER_EXT - - 1 - 1 + 1 + 1 - 97 - Int + 97 + Int -
+ SMALL_INTEGER_EXT

- Unsigned 8 bit integer. + Unsigned 8-bit integer.

INTEGER_EXT - - 1 - 4 + 1 + 4 - 98 - Int + 98 + Int -
+ INTEGER_EXT

- Signed 32 bit integer in big-endian format (i.e. MSB first) + Signed 32-bit integer in big-endian format (that is, MSB first).

FLOAT_EXT - - 1 - 31 + 1 + 31 - 99 - Float String + 99 + Float string -
+ FLOAT_EXT

- A float is stored in string format. the format used in sprintf to - format the float is "%.20e" + A float is stored in string format. The format used in sprintf to + format the float is "%.20e" (there are more bytes allocated than necessary). - To unpack the float use sscanf with format "%lf". + To unpack the float, use sscanf with format "%lf".

- This term is used in minor version 0 of the external format; - it has been superseded by - - NEW_FLOAT_EXT - . + This term is used in minor version 0 of the external format; + it has been superseded by + NEW_FLOAT_EXT.

ATOM_EXT - - 1 - 2 - Len + 1 + 2 + Len - 100 - Len - AtomName + 100 + Len + AtomName -
+ ATOM_EXT

- An atom is stored with a 2 byte unsigned length in big-endian order, - followed by Len numbers of 8 bit Latin1 characters that forms - the AtomName. - Note: The maximum allowed value for Len is 255. + An atom is stored with a 2 byte unsigned length in big-endian order, + followed by Len numbers of 8-bit Latin-1 characters that forms + the AtomName. The maximum allowed value for Len is 255.

REFERENCE_EXT - - - - 1 - N - 4 - 1 - - - 101 - Node - ID - Creation - -
+ + + 1 + N + 4 + 1 + + + 101 + Node + ID + Creation + + REFERENCE_EXT

- Encode a reference object (an object generated with make_ref/0). - The Node term is an encoded atom, i.e. - ATOM_EXT, - SMALL_ATOM_EXT or - ATOM_CACHE_REF. - The ID field contains a big-endian - unsigned integer, - but should be regarded as uninterpreted data - since this field is node specific. - Creation is a byte containing a node serial number that - makes it possible to separate old (crashed) nodes from a new one. + Encodes a reference object (an object generated with + erlang:make_ref/0). + The Node term is an encoded atom, that is, + ATOM_EXT, + SMALL_ATOM_EXT, or + ATOM_CACHE_REF. + The ID field contains a big-endian unsigned integer, + but is to be regarded as uninterpreted data, + as this field is node-specific. + Creation is a byte containing a node serial number, which + makes it possible to separate old (crashed) nodes from a new one.

- In ID, only 18 bits are significant; the rest should be 0. - In Creation, only 2 bits are significant; the rest should be 0. - - See NEW_REFERENCE_EXT. + In ID, only 18 bits are significant; the rest are to be 0. + In Creation, only two bits are significant; the rest are to be 0. + See + NEW_REFERENCE_EXT.

PORT_EXT - 1 @@ -483,20 +470,21 @@ ID Creation -
+ PORT_EXT

- Encode a port object (obtained form open_port/2). - The ID is a node specific identifier for a local port. + Encodes a port object (obtained from + + erlang:open_port/2). + The ID is a node-specific identifier for a local port. Port operations are not allowed across node boundaries. The Creation works just like in - REFERENCE_EXT. + REFERENCE_EXT.

PID_EXT - 1 @@ -512,23 +500,20 @@ Serial Creation -
+ PID_EXT

- Encode a process identifier object (obtained from spawn/3 or - friends). - The ID and Creation fields works just like in - REFERENCE_EXT, while - the Serial field is used to improve safety. - - In ID, only 15 bits are significant; the rest should be 0. + Encodes a process identifier object (obtained from + erlang:spawn/3 or + friends). The ID and Creation fields works just like in + REFERENCE_EXT, while + the Serial field is used to improve safety. + In ID, only 15 bits are significant; the rest are to be 0.

-
SMALL_TUPLE_EXT - 1 @@ -536,22 +521,21 @@ N - 104 - Arity - Elements + 104 + Arity + Elements -
+ SMALL_TUPLE_EXT

- SMALL_TUPLE_EXT encodes a tuple. The Arity - field is an unsigned byte that determines how many element - that follows in the Elements section. + Encodes a tuple. The Arity + field is an unsigned byte that determines how many elements + that follows in section Elements.

LARGE_TUPLE_EXT - 1 @@ -559,23 +543,22 @@ N - 105 - Arity - Elements + 105 + Arity + Elements -
+ LARGE_TUPLE_EXT

- Same as - SMALL_TUPLE_EXT - with the exception that Arity is an - unsigned 4 byte integer in big endian format. + Same as + SMALL_TUPLE_EXT + except that Arity is an + unsigned 4 byte integer in big-endian format.

MAP_EXT - 1 @@ -583,43 +566,42 @@ N - 116 - Arity - Pairs + 116 + Arity + Pairs -
+ MAP_EXT

- MAP_EXT encodes a map. The Arity field is an unsigned - 4 byte integer in big endian format that determines the number of + Encodes a map. The Arity field is an unsigned + 4 byte integer in big-endian format that determines the number of key-value pairs in the map. Key and value pairs (Ki => Vi) - are encoded in the Pairs section in the following order: + are encoded in section Pairs in the following order: K1, V1, K2, V2,..., Kn, Vn. Duplicate keys are not allowed within the same map.

-

Since: OTP 17.0

+

As from Erlang/OTP 17.0

NIL_EXT - 1 - 106 + 106 -
+ NIL_EXT

- The representation for an empty list, i.e. the Erlang syntax []. + The representation for an empty list, that is, the Erlang syntax + [].

STRING_EXT - 1 @@ -627,27 +609,25 @@ Len - 107 - Length - Characters + 107 + Length + Characters -
+ STRING_EXT

- String does NOT have a corresponding Erlang representation, + 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 Length field is an unsigned 2 byte integer - (big endian), implementations must make sure that lists longer than - 65535 elements are encoded as - LIST_EXT. + As field Length is an unsigned 2 byte integer + (big-endian), implementations must ensure that lists longer than + 65535 elements are encoded as + LIST_EXT.

-
LIST_EXT - 1 @@ -656,27 +636,24 @@   - 108 - Length - Elements - Tail + 108 + Length + Elements + Tail -
- + LIST_EXT

- Length is the number of elements that follows in the - Elements section. Tail is the final tail of - the list; it is - NIL_EXT - for a proper list, but may be anything type if the list is - improper (for instance [a|b]). + Length is the number of elements that follows in section + Elements. Tail is the final tail of the list; it is + NIL_EXT + for a proper list, but can be any type if the list is + improper (for example, [a|b]).

BINARY_EXT - 1 @@ -684,25 +661,26 @@ Len - 109 - Len - Data + 109 + Len + Data -
+ BINARY_EXT

Binaries are generated with bit syntax expression or with - list_to_binary/1, - term_to_binary/1, + + erlang:list_to_binary/1, + + erlang:term_to_binary/1, or as input from binary ports. - The Len length field is an unsigned 4 byte integer - (big endian). + The Len length field is an unsigned 4 byte integer + (big-endian).

SMALL_BIG_EXT - 1 @@ -711,27 +689,26 @@ n - 110 - n - Sign - d(0) ... d(n-1) + 110 + n + Sign + d(0) ... d(n-1) -
+ SMALL_BIG_EXT

- Bignums are stored in unary form with a Sign 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:
- - B = 256
- (d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1)) + Bignums are stored in unary form with a Sign byte, + that is, 0 if the binum is positive and 1 if it is negative. The + digits are stored with the least significant byte stored first. To + calculate the integer, the following formula can be used: +

+

B = 256
+ (d0*B^0 + d1*B^1 + d2*B^2 + ... d(N-1)*B^(n-1))

LARGE_BIG_EXT - 1 @@ -740,24 +717,22 @@ n - 111 - n - Sign - d(0) ... d(n-1) + 111 + n + Sign + d(0) ... d(n-1) -
+ LARGE_BIG_EXT

- Same as SMALL_BIG_EXT - with the difference that the length field - is an unsigned 4 byte integer. + Same as + SMALL_BIG_EXT + except that the length field is an unsigned 4 byte integer.

-
NEW_REFERENCE_EXT - 1 @@ -767,44 +742,43 @@ N' - 114 - Len - Node - Creation - ID ... + 114 + Len + Node + Creation + ID ... -
+ NEW_REFERENCE_EXT

- Node and Creation are as in - REFERENCE_EXT. + Node and Creation are as in + REFERENCE_EXT.

- ID contains a sequence of big-endian unsigned integers - (4 bytes each, so N' is a multiple of 4), - but should be regarded as uninterpreted data. + ID contains a sequence of big-endian unsigned integers + (4 bytes each, so N' is a multiple of 4), + but is to be regarded as uninterpreted data.

N' = 4 * Len.

- In the first word (four bytes) of ID, only 18 bits are - significant, the rest should be 0. - In Creation, only 2 bits are significant, - the rest should be 0. + In the first word (4 bytes) of ID, only 18 bits are + significant, the rest are to be 0. + In Creation, only two bits are significant, + the rest are to be 0.

- NEW_REFERENCE_EXT was introduced with distribution version 4. - In version 4, N' should be at most 12. + NEW_REFERENCE_EXT was introduced with distribution version 4. + In version 4, N' is to be at most 12.

- See REFERENCE_EXT). + See REFERENCE_EXT.

SMALL_ATOM_EXT - 1 @@ -816,24 +790,28 @@ Len AtomName -
+ SMALL_ATOM_EXT

- An atom is stored with a 1 byte unsigned length, - followed by Len numbers of 8 bit Latin1 characters that + An atom is stored with a 1 byte unsigned length, + followed by Len numbers of 8-bit Latin-1 characters that forms the AtomName. Longer atoms can be represented - by ATOM_EXT. Note - the SMALL_ATOM_EXT was introduced in erts version 5.7.2 and - require an exchange of the - DFLAG_SMALL_ATOM_TAGS - distribution flag in the - distribution handshake. + by ATOM_EXT.

+ +

+ SMALL_ATOM_EXT was introduced in ERTS 5.7.2 and + require an exchange of distribution flag + + DFLAG_SMALL_ATOM_TAGS in the + + distribution handshake. +

+
FUN_EXT - 1 @@ -845,48 +823,56 @@ N5 - 117 - NumFree - Pid - Module - Index - Uniq - Free vars ... + 117 + NumFree + Pid + Module + Index + Uniq + Free vars ... -
+ FUN_EXT - Pid + Pid - is a process identifier as in - PID_EXT. - It represents the process in which the fun was created. +

A process identifier as in + PID_EXT. + Represents the process in which the fun was created. +

Module - is an encoded as an atom, using - ATOM_EXT, - SMALL_ATOM_EXT - or ATOM_CACHE_REF. - This is the module that the fun is implemented in. +

Encoded as an atom, using + ATOM_EXT, + SMALL_ATOM_EXT, + or + ATOM_CACHE_REF. + This is the module that the fun is implemented in. +

Index - is an integer encoded using - SMALL_INTEGER_EXT - or INTEGER_EXT. - It is typically a small index into the module's fun table. +

An integer encoded using + + SMALL_INTEGER_EXT + or INTEGER_EXT. + It is typically a small index into the module's fun table. +

Uniq - is an integer encoded using - SMALL_INTEGER_EXT or - INTEGER_EXT. - Uniq is the hash value of the parse for the fun. +

An integer encoded using + + SMALL_INTEGER_EXT or + INTEGER_EXT. + Uniq is the hash value of the parse for the fun. +

Free vars - is NumFree number of terms, each one encoded according - to its type. +

NumFree number of terms, each one encoded according + to its type. +

@@ -894,7 +880,6 @@
NEW_FUN_EXT - 1 @@ -910,19 +895,19 @@ N5 - 112 - Size - Arity - Uniq - Index - NumFree - Module - OldIndex - OldUniq - Pid - Free Vars + 112 + Size + Arity + Uniq + Index + NumFree + Module + OldIndex + OldUniq + Pid + Free Vars -
+ NEW_FUN_EXT

This is the new encoding of internal funs: fun F/A and fun(Arg1,..) -> ... end. @@ -930,68 +915,73 @@ Size - is the total number of bytes, including the Size field. +

The total number of bytes, including field Size.

Arity - is the arity of the function implementing the fun. +

The arity of the function implementing the fun.

Uniq - is the 16 bytes MD5 of the significant parts of the Beam file. +

The 16 bytes MD5 of the significant parts of the Beam file.

Index - is an index number. Each fun within a module has an unique - index. Index is stored in big-endian byte order. +

An index number. Each fun within a module has an unique + index. Index is stored in big-endian byte order. +

NumFree - is the number of free variables. +

The number of free variables.

Module - is an encoded as an atom, using - ATOM_EXT, - SMALL_ATOM_EXT or - ATOM_CACHE_REF. - This is the module that the fun is implemented in. +

Encoded as an atom, using + ATOM_EXT, + SMALL_ATOM_EXT, + or + ATOM_CACHE_REF. + Is the module that the fun is implemented in. +

OldIndex - is an integer encoded using - SMALL_INTEGER_EXT - or INTEGER_EXT. - It is typically a small index into the module's fun table. +

An integer encoded using + + SMALL_INTEGER_EXT or + INTEGER_EXT. + Is typically a small index into the module's fun table. +

OldUniq - is an integer encoded using - SMALL_INTEGER_EXT - or - INTEGER_EXT. - Uniq is the hash value of the parse tree for the fun. +

An integer encoded using + + SMALL_INTEGER_EXT or + INTEGER_EXT. + Uniq is the hash value of the parse tree for the fun. +

Pid - is a process identifier as in - PID_EXT. - It represents the process in which - the fun was created. +

A process identifier as in + PID_EXT. + Represents the process in which the fun was created. +

- Free vars - is NumFree number of terms, each one encoded according - to its type. +

NumFree number of terms, each one encoded according + to its type. +

- EXPORT_EXT - + EXPORT_EXT 1 @@ -1000,32 +990,31 @@ N3 - 113 - Module - Function - Arity + 113 + Module + Function + Arity -
+ EXPORT_EXT

This term is the encoding for external funs: fun M:F/A.

- Module and Function are atoms - (encoded using ATOM_EXT, - SMALL_ATOM_EXT or - ATOM_CACHE_REF). + Module and Function are atoms + (encoded using ATOM_EXT, + SMALL_ATOM_EXT, or + ATOM_CACHE_REF).

- Arity is an integer encoded using - SMALL_INTEGER_EXT. + Arity is an integer encoded using + + SMALL_INTEGER_EXT.

-
BIT_BINARY_EXT - 1 @@ -1034,39 +1023,35 @@ Len - 77 - Len - Bits - Data + 77 + Len + Bits + Data -
+ BIT_BINARY_EXT

This term represents a bitstring whose length in bits does not have to be a multiple of 8. - The Len field is an unsigned 4 byte integer (big endian). + The Len field is an unsigned 4 byte integer (big-endian). The Bits field is the number of bits (1-8) that are used - in the last byte in the data field, - counting from the most significant bit towards the least - significant. + in the last byte in the data field, + counting from the most significant bit to the least significant.

- -
NEW_FLOAT_EXT - 1 8 - 70 - IEEE float + 70 + IEEE float -
+ NEW_FLOAT_EXT

A float is stored as 8 bytes in big-endian IEEE format.

@@ -1074,10 +1059,10 @@ This term is used in minor version 1 of the external format.

+
ATOM_UTF8_EXT - 1 @@ -1089,23 +1074,22 @@ Len AtomName -
+ ATOM_UTF8_EXT

An atom is stored with a 2 byte unsigned length in big-endian order, followed by Len bytes containing the AtomName encoded in UTF-8.

- For more information on encoding of atoms, see + For more information on encoding of atoms, see the note on UTF-8 encoded atoms - in the beginning of this document. + in the beginning of this section.

SMALL_ATOM_UTF8_EXT - 1 @@ -1117,20 +1101,19 @@ Len AtomName -
+ SMALL_ATOM_UTF8_EXT

- An atom is stored with a 1 byte unsigned length, + An atom is stored with a 1 byte unsigned length, followed by Len bytes containing the AtomName encoded in UTF-8. Longer atoms encoded in UTF-8 can be represented using - ATOM_UTF8_EXT. + ATOM_UTF8_EXT.

- For more information on encoding of atoms, see + For more information on encoding of atoms, see the note on UTF-8 encoded atoms - in the beginning of this document. + in the beginning of this section.

- - + diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 8ed042f6f9..d154a1bd21 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -33,43 +33,52 @@ erl_nif.xml erl_nif - API functions for an Erlang NIF library + API functions for an Erlang NIF library.

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.

- -

Use this functionality with extreme care!

+ of an Erlang module. The native implemented functions (NIFs) are + called like any other functions without any difference to the + caller. Each NIF must have an implementation in Erlang that + is invoked if the function is called before the NIF library + is successfully loaded. A typical such stub implementation + is to throw an exception. But it can also be used as a fallback + implementation if the NIF library is not implemented for some + architecture.

+ + + +

Use this functionality with extreme care.

A native function is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can not provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the native function doesn't behave well, the whole - VM will misbehave.

- -

A native function that crash will crash the whole VM.

-

An erroneously implemented native function might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the native function.

-

A native function that do lengthy - work before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.

+ native code of the VM. Execution is not made in a safe environment. + The VM cannot provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the native function does not behave well, the whole + VM will misbehave.

+ + +

A native function that crash will crash the whole VM.

+
+ +

An erroneously implemented native function can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the native function.

+
+ +

A native function doing lengthy + work before returning degrades responsiveness of the VM, + and can cause miscellaneous strange behaviors. Such strange + behaviors include, but are not limited to, extreme memory usage, + and bad load balancing between schedulers. Strange behaviors that + can occur because of lengthy work can also vary between Erlang/OTP + releases.

+
-
+
+ +

A minimal example of a NIF library can look as follows:

-

A minimal example of a NIF library can look like this:

-

- + /* niftest.c */ #include "erl_nif.h" @@ -83,13 +92,11 @@ static ErlNifFunc nif_funcs[] = {"hello", 0, hello} }; -ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL) - +ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL) -

and the Erlang module would have to look something like - this:

-

- +

The Erlang module can look as follows:

+ + -module(niftest). -export([init/0, hello/0]). @@ -98,11 +105,11 @@ init() -> erlang:load_nif("./niftest", 0). hello() -> - "NIF library not loaded". - -

and compile and test something like this (on Linux):

-

- + "NIF library not loaded". + +

Compile and test can look as follows (on Linux):

+ + $> gcc -fPIC -shared -o niftest.so niftest.c -I $ERL_ROOT/usr/include/ $> erl @@ -113,290 +120,310 @@ $> erl 3> niftest:init(). ok 4> niftest:hello(). -"Hello world!" - - -

A better solution for a real module is to take advantage of - the new directive on_load to automatically - load the NIF library when the module is loaded.

-

A NIF does not have to be exported, it can be local to the module. - Note however that unused local stub functions will be optimized - away by the compiler causing loading of the NIF library to fail.

+"Hello world!"
+ +

A better solution for a real module is to take advantage of the new + directive on load (see section + Running a + Function When a Module is Loaded in the Erlang Reference + Manual) to load the NIF library automatically when the module is + loaded.

+ + +

A NIF does not have to be exported, it can be local to the module. + However, unused local stub functions will be optimized + away by the compiler, causing loading of the NIF library to fail.

-

A loaded NIF library is tied to the Erlang module code version - that loaded it. If the module is upgraded with a new version, the - new Erlang code will have to load its own NIF library (or maybe choose not - to). The new code version can however choose to load the exact - same NIF library as the old code if it wants to. Sharing the same - dynamic library will mean that static data defined by the library - will be shared as well. To avoid unintentionally shared static - data, each Erlang module code can keep its own private data. This - private data can be set when the NIF library is loaded and - then retrieved by calling enif_priv_data.

-

There is no way to explicitly unload a NIF library. A library will be - automatically unloaded when the module code that it belongs to is purged - by the code server.

- +

A loaded NIF library is tied to the Erlang module code version + that loaded it. If the module is upgraded with a new version, the + new Erlang code need to load its own NIF library (or maybe choose not + to). The new code version can, however, choose to load the + same NIF library as the old code if it wants to. Sharing the + dynamic library means that static data defined by the library + is shared as well. To avoid unintentionally shared static + data, each Erlang module code can keep its own private data. This + private data can be set when the NIF library is loaded and + then retrieved by calling + enif_priv_data.

+ +

A NIF library cannot be loaded explicitly. A library is + automatically unloaded when the module code that it belongs to is purged + by the code server.

+
- FUNCTIONALITY -

All functions that a NIF library needs to do with Erlang are - performed through the NIF API functions. There are functions + Functionality +

All functions that a NIF library needs to do with Erlang are + performed through the NIF API functions. Functions exist for the following functionality:

+ Read and write Erlang terms -

Any Erlang terms can be passed to a NIF as function arguments and - be returned as function return values. The terms are of C-type - ERL_NIF_TERM - and can only be read or written using API functions. Most functions to read - the content of a term are prefixed enif_get_ and usually return - true (or false) if the term was of the expected type (or not). - The functions to write terms are all prefixed enif_make_ and usually - return the created ERL_NIF_TERM. There are also some functions - to query terms, like enif_is_atom, enif_is_identical and - enif_compare.

-

All terms of type ERL_NIF_TERM belong to an environment of type - ErlNifEnv. The lifetime of a term is - controlled by the lifetime of its environment object. All API functions that read - or write terms has the environment, that the term belongs to, as the first - function argument.

+ +

Any Erlang terms can be passed to a NIF as function arguments and + be returned as function return values. The terms are of C-type + ERL_NIF_TERM and can + only be read or written using API functions. Most functions to read + the content of a term are prefixed enif_get_ and usually return + true (or false) if the term is of the expected type (or + not). The functions to write terms are all prefixed enif_make_ + and usually + return the created ERL_NIF_TERM. There are also some functions + to query terms, like enif_is_atom, enif_is_identical, + and enif_compare.

+

All terms of type ERL_NIF_TERM belong to an environment of + type ErlNifEnv. The + lifetime of a term is controlled by the lifetime of its environment + object. All API functions that read or write terms has the + environment that the term belongs to as the first function + argument.

+
Binaries -

Terms of type binary are accessed with the help of the struct type - ErlNifBinary - that contains a pointer (data) to the raw binary data and the length - (size) of the data in bytes. Both data and size are - read-only and should only be written using calls to API functions. - Instances of ErlNifBinary are however always allocated by the user - (usually as local variables).

-

The raw data pointed to by data is only mutable after a call to - enif_alloc_binary or - enif_realloc_binary. - All other functions that operates on a binary will leave the data as read-only. - A mutable binary must in the end either be freed with - enif_release_binary - or made read-only by transferring it to an Erlang term with - enif_make_binary. - But it does not have to happen in the same NIF call. Read-only binaries - do not have to be released.

-

enif_make_new_binary - can be used as a shortcut to allocate and return a binary in the same NIF call.

-

Binaries are sequences of whole bytes. Bitstrings with an arbitrary - bit length have no support yet.

-
+ +

Terms of type binary are accessed with the help of struct type + ErlNifBinary, + which contains a pointer (data) to the raw binary data and the + length (size) of the data in bytes. Both data and + size are read-only and are only to be written using calls to + API functions. Instances of ErlNifBinary are, however, always + allocated by the user (usually as local variables).

+

The raw data pointed to by data is only mutable after a call + to + enif_alloc_binary or + + enif_realloc_binary. All other functions that + operate on a binary leave the data as read-only. + A mutable binary must in the end either be freed with + + enif_release_binary + or made read-only by transferring it to an Erlang term with + enif_make_binary. + However, it does not have to occur in the same NIF call. Read-only + binaries do not have to be released.

+

+ enif_make_new_binary can be used as a shortcut to + allocate and return a binary in the same NIF call.

+

Binaries are sequences of whole bytes. Bitstrings with an arbitrary + bit length have no support yet.

+
Resource objects -

The use of resource objects is a safe way to return pointers to - native data structures from a NIF. A resource object is - just a block of memory allocated with - enif_alloc_resource. - A handle ("safe pointer") to this memory block can then be returned to Erlang by the use of - enif_make_resource. - The term returned by enif_make_resource - is totally opaque in nature. It can be stored and passed between processes - on the same node, but the only real end usage is to pass it back as an argument to a NIF. - The NIF can then call enif_get_resource - and get back a pointer to the memory block that is guaranteed to still be - valid. A resource object will not be deallocated until the last handle term - has been garbage collected by the VM and the resource has been - released with enif_release_resource - (not necessarily in that order).

-

All resource objects are created as instances of some resource type. - This makes resources from different modules to be distinguishable. - A resource type is created by calling - enif_open_resource_type - when a library is loaded. Objects of that resource type can then later be allocated - and enif_get_resource verifies that the resource is of the expected type. - A resource type can have a user supplied destructor function that is - automatically called when resources of that type are released (by either - the garbage collector or enif_release_resource). Resource types - are uniquely identified by a supplied name string and the name of the - implementing module.

-

Here is a template example of how to create and return a resource object.

-

- - ERL_NIF_TERM term; - MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); - - /* initialize struct ... */ - - term = enif_make_resource(env, obj); - - if (keep_a_reference_of_our_own) { - /* store 'obj' in static variable, private data or other resource object */ - } - else { - enif_release_resource(obj); - /* resource now only owned by "Erlang" */ - } - return term; - -

Note that once enif_make_resource creates the term to - return to Erlang, the code can choose to either keep its own - native pointer to the allocated struct and release it later, or - release it immediately and rely solely on the garbage collector - to eventually deallocate the resource object when it collects - the term.

-

Another usage of resource objects is to create binary terms with - user defined memory management. - enif_make_resource_binary - will create a binary term that is connected to a resource object. The - destructor of the resource will be called when the binary is garbage - collected, at which time the binary data can be released. An example of - this can be a binary term consisting of data from a mmap'ed file. - The destructor can then do munmap to release the memory - region.

-

Resource types support upgrade in runtime by allowing a loaded NIF - library to takeover an already existing resource type and thereby - "inherit" all existing objects of that type. The destructor of the new - library will thereafter be called for the inherited objects and the - library with the old destructor function can be safely unloaded. Existing - resource objects, of a module that is upgraded, must either be deleted - or taken over by the new NIF library. The unloading of a library will be - postponed as long as there exist resource objects with a destructor - function in the library. -

+ +

The use of resource objects is a safe way to return pointers to + native data structures from a NIF. A resource object is + only a block of memory allocated with + + enif_alloc_resource. + A handle ("safe pointer") to this memory block can then be returned + to Erlang by the use of + + enif_make_resource. + The term returned by enif_make_resource is opaque in nature. + It can be stored and passed between processes on the same node, but + the only real end usage is to pass it back as an argument to a NIF. + The NIF can then call + enif_get_resource and get back a pointer to the + memory block, which is guaranteed to still be valid. A resource + object is not deallocated until the last handle term + is garbage collected by the VM and the resource is released with + + enif_release_resource + (not necessarily in that order).

+

All resource objects are created as instances of some resource + type. This makes resources from different modules to be + distinguishable. A resource type is created by calling + + enif_open_resource_type when a library is loaded. + Objects of that resource type can then later be allocated and + enif_get_resource verifies that the resource is of the + expected type. A resource type can have a user-supplied destructor + function, which is automatically called when resources of that type + are released (by either the garbage collector or + enif_release_resource). Resource types are uniquely identified + by a supplied name string and the name of the implementing module.

+ +

The following is a template example of how to create and return a + resource object.

+ +ERL_NIF_TERM term; +MyStruct* obj = enif_alloc_resource(my_resource_type, sizeof(MyStruct)); + +/* initialize struct ... */ + +term = enif_make_resource(env, obj); + +if (keep_a_reference_of_our_own) { + /* store 'obj' in static variable, private data or other resource object */ +} +else { + enif_release_resource(obj); + /* resource now only owned by "Erlang" */ +} +return term; +

Notice that once enif_make_resource creates the term to + return to Erlang, the code can choose to either keep its own + native pointer to the allocated struct and release it later, or + release it immediately and rely only on the garbage collector + to deallocate the resource object eventually when it collects + the term.

+

Another use of resource objects is to create binary terms with + user-defined memory management. + + enif_make_resource_binary + creates a binary term that is connected to a resource object. The + destructor of the resource is called when the binary is garbage + collected, at which time the binary data can be released. An example + of this can be a binary term consisting of data from a mmap'ed + file. The destructor can then do munmap to release the memory + region.

+

Resource types support upgrade in runtime by allowing a loaded NIF + library to take over an already existing resource type and by that + "inherit" all existing objects of that type. The destructor of the + new library is thereafter called for the inherited objects and the + library with the old destructor function can be safely unloaded. + Existing resource objects, of a module that is upgraded, must either + be deleted or taken over by the new NIF library. The unloading of a + library is postponed as long as there exist resource objects with a + destructor function in the library.

Threads and concurrency -

A NIF is thread-safe without any explicit synchronization as - long as it acts as a pure function and only reads the supplied - arguments. As soon as you write towards a shared state either through - static variables or enif_priv_data - you need to supply your own explicit synchronization. This includes terms - in process independent environments that are shared between threads. - Resource objects will also require synchronization if you treat them as - mutable.

-

The library initialization callbacks load, reload and - upgrade are all thread-safe even for shared state data.

+ +

A NIF is thread-safe without any explicit synchronization as + long as it acts as a pure function and only reads the supplied + arguments. When you write to a shared state either through + static variables or + enif_priv_data, you need to supply your own explicit + synchronization. This includes terms in process-independent + environments that are shared between threads. Resource objects also + require synchronization if you treat them as mutable.

+

The library initialization callbacks load, reload, and + upgrade are all thread-safe even for shared state data.

- Version Management -

- When a NIF library is built, information about NIF API version - is compiled into the library. When a NIF library is loaded the - runtime system verifies that the library is of a compatible version. - erl_nif.h defines ERL_NIF_MAJOR_VERSION, and - ERL_NIF_MINOR_VERSION. ERL_NIF_MAJOR_VERSION will be - incremented when NIF library incompatible changes are made to the - Erlang runtime system. Normally it will suffice to recompile the NIF - library when the ERL_NIF_MAJOR_VERSION has changed, but it - could, under rare circumstances, mean that NIF libraries have to - be slightly modified. If so, this will of course be documented. - ERL_NIF_MINOR_VERSION will be incremented when - new features are added. The runtime system uses the minor version - to determine what features to use. -

- The runtime system will normally refuse to load a NIF library if - the major versions differ, or if the major versions are equal and - the minor version used by the NIF library is greater than the one - used by the runtime system. Old NIF libraries with lower major - versions will however be allowed after a bump of the major version - during a transition period of two major releases. Such old NIF - libraries might however fail if deprecated features are used. -

- + +

When a NIF library is built, information about the NIF API version + is compiled into the library. When a NIF library is loaded, the + runtime system verifies that the library is of a compatible version. + erl_nif.h defines the following:

+ + ERL_NIF_MAJOR_VERSION + +

Incremented when NIF library incompatible changes are made to the + Erlang runtime system. Normally it suffices to recompile the NIF + library when the ERL_NIF_MAJOR_VERSION has changed, but it + can, under rare circumstances, mean that NIF libraries must be + slightly modified. If so, this will of course be documented.

+
+ ERL_NIF_MINOR_VERSION + +

Incremented when new features are added. The runtime system uses + the minor version to determine what features to use.

+
+
+

The runtime system normally refuses to load a NIF library if + the major versions differ, or if the major versions are equal and + the minor version used by the NIF library is greater than the one + used by the runtime system. Old NIF libraries with lower major + versions are, however, allowed after a bump of the major version + during a transition period of two major releases. Such old NIF + libraries can however fail if deprecated features are used.

+
Time Measurement -

Support for time measurement in NIF libraries:

- - ErlNifTime - ErlNifTimeUnit - enif_monotonic_time() - enif_time_offset() - enif_convert_time_unit() + +

Support for time measurement in NIF libraries:

+ + + ErlNifTime + + ErlNifTimeUnit + + enif_monotonic_time() + + enif_time_offset() + + enif_convert_time_unit()
- Long-running NIFs - -

- As mentioned in the warning text at - the beginning of this document it is of vital importance that a - native function return relatively quickly. It is hard to give an exact - maximum amount of time that a native function is allowed to work, but as a - rule of thumb a well-behaving native function should return to its caller - before a millisecond has passed. This can be achieved using different - approaches. If you have full control over the code to execute in the - native function, the best approach is to divide the work into multiple - chunks of work and call the native function multiple times. In some - cases this might however not always be possible, e.g. when calling - third-party libraries.

- -

The - enif_consume_timeslice() - function can be used to inform the runtime system about the length of the - NIF call. It should typically always be used unless the NIF executes very - quickly.

- -

If the NIF call is too lengthy one needs to handle this in one of the - following ways in order to avoid degraded responsiveness, scheduler load - balancing problems, and other strange behaviors:

- - - Yielding NIF - -

- If the functionality of a long-running NIF can be split so that - its work can be achieved through a series of shorter NIF calls, - the application can either make that series of NIF calls from the - Erlang level, or it can call a NIF that first performs a chunk of - the work, then invokes the - enif_schedule_nif - function to schedule another NIF call to perform the next chunk. - The final call scheduled in this manner can then return the - overall result. Breaking up a long-running function in - this manner enables the VM to regain control between calls to the - NIFs. -

-

- This approach is always preferred over the other alternatives - described below. This both from a performance perspective and - a system characteristics perspective. -

-
- - Threaded NIF - -

- This is accomplished by dispatching the work to another thread - managed by the NIF library, return from the NIF, and wait for the - result. The thread can send the result back to the Erlang - process using enif_send. - Information about thread primitives can be found below. -

-
- - Dirty NIF - - - -

- The dirty NIF functionality described here - is experimental. Dirty NIF support is available only when - the emulator is configured with dirty schedulers enabled. This - feature is currently disabled by default. The Erlang runtime - without SMP support do not support dirty schedulers even when - the dirty scheduler support has been enabled. To check at - runtime for the presence of dirty scheduler threads, code can - use the - enif_system_info() - API function. -

-
- -

- A NIF that cannot be split and cannot execute in a millisecond or - less is called a "dirty NIF" because it performs work that the - ordinary schedulers of the Erlang runtime system cannot handle cleanly. - Applications that make use of such functions must indicate to the - runtime that the functions are dirty so they can be handled - specially. This is handled by executing dirty jobs on a separate + +

As mentioned in the warning text + at the beginning of this manual page, it is of vital + importance that a native function returns relatively fast. It is + difficult to give an exact maximum amount of time that a native + function is allowed to work, but usually a well-behaving native + function is to return to its caller within 1 millisecond. This can be + achieved using different approaches. If you have full control over the + code to execute in the native function, the best approach is to + divide the work into multiple chunks of work and call the native + function multiple times. This is, however, not always possible, for + example when calling third-party libraries.

+

The + enif_consume_timeslice() function can be used to + inform the runtime system about the length of the NIF call. + It is typically always to be used unless the NIF executes very + fast.

+

If the NIF call is too lengthy, this must be handled in one of + the following ways to avoid degraded responsiveness, scheduler load + balancing problems, and other strange behaviors:

+ + Yielding NIF + +

If the functionality of a long-running NIF can be split so that + its work can be achieved through a series of shorter NIF calls, + the application has two options:

+ + +

Make that series of NIF calls from the Erlang level.

+
+ +

Call a NIF that first performs a chunk of the work, then + invokes the + enif_schedule_nif function to schedule + another NIF call to perform the next chunk. The final call + scheduled in this manner can then return the overall + result.

+
+
+

Breaking up a long-running function in this manner enables the + VM to regain control between calls to the NIFs.

+

This approach is always preferred over the other alternatives + described below. This both from a performance perspective and + a system characteristics perspective.

+
+ Threaded NIF + +

This is accomplished by dispatching the work to another thread + managed by the NIF library, return from the NIF, and wait for + the result. The thread can send the result back to the Erlang + process using + enif_send. + Information about thread primitives is provided below.

+
+ Dirty NIF + + +

The dirty NIF functionality described here + is experimental. Dirty NIF support is available only when + the emulator is configured with dirty schedulers enabled. This + feature is disabled by default. The Erlang runtime + without SMP support does not support dirty schedulers even when + the dirty scheduler support is enabled. To check at runtime for + the presence of dirty scheduler threads, code can use the + + enif_system_info() API function.

+
+

A NIF that cannot be split and cannot execute in a millisecond + or less is called a "dirty NIF", as it performs work that the + ordinary schedulers of the Erlang runtime system cannot handle cleanly. + Applications that make use of such functions must indicate to the + runtime that the functions are dirty so they can be handled + specially. This is handled by executing dirty jobs on a separate set of schedulers called dirty schedulers. A dirty NIF executing on a dirty scheduler does not have the same duration restriction as a normal NIF. -

- -

- It is important to classify the dirty job correct. An I/O bound +

+

+ It is important to classify the dirty job correct. An I/O bound job should be classified as such, and a CPU bound job should be classified as such. If you should classify CPU bound jobs as I/O bound jobs, dirty I/O schedulers might starve ordinary @@ -404,1240 +431,1636 @@ ok for I/O, and/or spend a limited amount of time moving data.

-

- To schedule a dirty NIF for execution, the appropriate - flags value can be set for the NIF in its - ErlNifFunc - entry, or the application can call - enif_schedule_nif, - passing to it a pointer to the dirty NIF to be executed and - indicating with the flags argument whether it expects the - operation to be CPU-bound or I/O-bound. A job that alternates - between I/O bound and CPU bound can be reclassified and - rescheduled using enif_schedule_nif so that it executes on - the correct type of dirty scheduler at all times. For more - information see the documentation of the erl command line - arguments +SDcpu, - and +SDio. -

- -

- While a process is executing a dirty NIF some operations that - communicate with it may take a very long time to complete. - Suspend, or garbage collection of a process executing a dirty - NIF cannot be done until the dirty NIF has returned, so other - processes waiting for such operations to complete might have to - wait for a very long time. Blocking multi scheduling, i.e., - calling - erlang:system_flag(multi_scheduling, - block), might also take a very long time to - complete. This since all ongoing dirty operations on all - dirty schedulers need to complete before the block - operation can complete. -

-

- A lot of operations communicating with a process executing a - dirty NIF can, however, complete while it is executing the - dirty NIF. For example, retrieving information about it via - process_info(), setting its group leader, - register/unregister its name, etc. -

-

- Termination of a process executing a dirty NIF can only be - completed up to a certain point while it is executing the - dirty NIF. All Erlang resources such as its registered name, - its ETS tables, etc will be released. All links and monitors - will be triggered. The actual execution of the NIF will - however not be stopped. The NIF can safely continue - execution, allocate heap memory, etc, but it is of course better - to stop executing as soon as possible. The NIF can check - whether current process is alive or not using - enif_is_current_process_alive. - Communication using - enif_send, - and enif_port_command - will also be dropped when the sending process is not alive. - Deallocation of certain internal resources such as process - heap, and process control block will be delayed until the - dirty NIF has completed. -

-

Currently known issues that are planned to be fixed:

- - -

- Since purging of a module currently might need to garbage - collect a process in order to determine if it has - references to the module, a process executing a dirty - NIF might delay purging for a very long time. Delaying - a purge operation implies delaying all code - loading operations which might cause severe problems for - the system as a whole. -

-
-
- -
-
- +

+ To schedule a dirty NIF for execution, the application has two options:

+ + +

Set the appropriate flags value for the dirty NIF in its + ErlNifFunc + entry.

+
+ +

Call + enif_schedule_nif, pass to it a pointer + to the dirty NIF to be executed, and indicate with argument + flags whether it expects the operation to be CPU-bound + or I/O-bound.

+
+
+

A job that alternates between I/O bound and CPU bound can be + reclassified and rescheduled using enif_schedule_nif so + that it executes on the correct type of dirty scheduler at all + times. For more information see the documentation of the + erl command line arguments + +SDcpu, + and +SDio.

+

While a process executes a dirty NIF, some operations that + communicate with it can take a very long time to complete. + Suspend or garbage collection of a process executing a dirty + NIF cannot be done until the dirty NIF has returned. Thus, other + processes waiting for such operations to complete might + have to wait for a very long time. Blocking multi-scheduling, that + is, calling + erlang:system_flag(multi_scheduling, block), can + also take a very long time to complete. This becaue all ongoing + dirty operations on all dirty schedulers must complete before + the block operation can complete.

+

Many operations communicating with a process executing a + dirty NIF can, however, complete while it executes the + dirty NIF. For example, retrieving information about it through + + erlang:process_info, setting its group leader, + register/unregister its name, and so on.

+

Termination of a process executing a dirty NIF can only be + completed up to a certain point while it executes the dirty NIF. + All Erlang resources, such as its registered name and its ets + tables, are released. All links and monitors are triggered. The + execution of the NIF is, however, not stopped. The NIF + can safely continue execution, allocate heap memory, and so on, + but it is of course better to stop executing as soon as possible. + The NIF can check whether a current process is alive using + + enif_is_current_process_alive. Communication + using enif_send and + + enif_port_command is also dropped when the + sending process is not alive. Deallocation of certain internal + resources, such as process heap and process control block, is + delayed until the dirty NIF has completed.

+

Known issue that are planned to be fixed:

+ + +

As purging of a module might need to garbage + collect a process to determine if it has + references to the module, a process executing a dirty + NIF can delay purging for a very long time. Delaying + a purge operation implies delaying all code + loading operations, which can cause severe problems for + the system as a whole.

+
+
+
+
+
- INITIALIZATION + Initialization - ERL_NIF_INIT(MODULE, ErlNifFunc funcs[], load, reload, upgrade, unload) -

This is the magic macro to initialize a NIF library. It - should be evaluated in global file scope.

-

MODULE is the name of the Erlang module as an - identifier without string quotations. It will be stringified by - the macro.

-

funcs is a static array of function descriptors for - all the implemented NIFs in this library.

-

load, reload, upgrade and unload - are pointers to functions. One of load, reload or - upgrade will be called to initialize the library. - unload is called to release the library. They are all - described individually below.

-

If compiling a nif for static inclusion via --enable-static-nifs you - have to define STATIC_ERLANG_NIF before the ERL_NIF_INIT declaration.

+ ERL_NIF_INIT(MODULE, + ErlNifFunc funcs[], load, reload, upgrade, unload) + +

This is the magic macro to initialize a NIF library. It + is to be evaluated in global file scope.

+

MODULE is the name of the Erlang module as an + identifier without string quotations. It is stringified by + the macro.

+

funcs is a static array of function descriptors for + all the implemented NIFs in this library.

+

load, reload, upgrade and unload + are pointers to functions. One of load, reload, or + upgrade is called to initialize the library. + unload is called to release the library. All are + described individually below.

+

If compiling a NIF for static inclusion through + --enable-static-nifs, you must define STATIC_ERLANG_NIF + before the ERL_NIF_INIT declaration.

- - int (*load)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) -

load is called when the NIF library is loaded - and there is no previously loaded library for this module.

+ int (*load)(ErlNifEnv* env, void** priv_data, + ERL_NIF_TERM load_info) + +

load is called when the NIF library is loaded + and no previously loaded library exists for this module.

*priv_data can be set to point to some private data - that the library needs in order to keep a state between NIF - calls. enif_priv_data will return this pointer. - *priv_data will be initialized to NULL when load is - called.

+ that the library needs to keep a state between NIF + calls. enif_priv_data returns this pointer. + *priv_data is initialized to NULL when load is + called.

load_info is the second argument to erlang:load_nif/2.

-

The library will fail to load if load returns - anything other than 0. load can be NULL in case no - initialization is needed.

-
- - int (*upgrade)(ErlNifEnv* env, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info) -

upgrade is called when the NIF library is loaded - and there is old code of this module with a loaded NIF library.

-

Works the same as load. The only difference is that - *old_priv_data already contains the value set by the - last call to load or reload for the old module - code. *priv_data will be initialized to NULL when upgrade - is called. It is allowed to write to both *priv_data and *old_priv_data.

-

The library will fail to load if upgrade returns - anything other than 0 or if upgrade is NULL.

+ marker="erlang#load_nif-2">erlang:load_nif/2.

+

The library fails to load if load returns + anything other than 0. load can be NULL if + initialization is not needed.

- - void (*unload)(ErlNifEnv* env, void* priv_data) -

unload is called when the module code that - the NIF library belongs to is purged as old. New code - of the same module may or may not exist. Note that unload is not - called for a replaced library as a consequence of reload.

+ int (*upgrade)(ErlNifEnv* env, void** + priv_data, void** old_priv_data, ERL_NIF_TERM load_info) + +

upgrade is called when the NIF library is loaded + and there is old code of this module with a loaded NIF library.

+

Works as load, except that *old_priv_data already + contains the value set by the last call to load or + reload for the old module code. *priv_data is + initialized to NULL when upgrade is called. It is + allowed to write to both *priv_data and + *old_priv_data.

+

The library fails to load if upgrade returns + anything other than 0 or if upgrade is NULL.

- - int (*reload)(ErlNifEnv* env, void** priv_data, ERL_NIF_TERM load_info) - - -

The reload mechanism is deprecated. It was only intended - as a development feature. Do not use it as an upgrade method for - live production systems. It might be removed in future releases. Be sure - to pass reload as NULL to ERL_NIF_INIT - to disable it when not used.

-
-

reload is called when the NIF library is loaded - and there is already a previously loaded library for this - module code.

-

Works the same as load. The only difference is that - *priv_data already contains the value set by the - previous call to load or reload.

-

The library will fail to load if reload returns - anything other than 0 or if reload is NULL.

+ void (*unload)(ErlNifEnv* env, void* + priv_data) + +

unload is called when the module code that + the NIF library belongs to is purged as old. New code of the same + module may or may not exist. Notice that unload is not + called for a replaced library as a consequence of reload.

+
+ int (*reload)(ErlNifEnv* env, void** + priv_data, ERL_NIF_TERM load_info) + + +

The reload mechanism is deprecated. It was only intended + as a development feature. Do not use it as an upgrade method for + live production systems. It can be removed in future releases. + Ensure to pass reload as NULL to + ERL_NIF_INIT + to disable it when not used.

+
+

reload is called when the NIF library is loaded and a + previously loaded library already exists for this module code.

+

Works as load, except that + *priv_data already contains the value set by the + previous call to load or reload.

+

The library fails to load if reload returns + anything other than 0 or if reload is NULL.

-
- DATA TYPES - + Data Types - ERL_NIF_TERM - + ERL_NIF_TERM +

Variables of type ERL_NIF_TERM can refer to any Erlang term. - This is an opaque type and values of it can only by used either as - arguments to API functions or as return values from NIFs. All - ERL_NIF_TERM's belong to an environment - (ErlNifEnv). A term can not be - destructed individually, it is valid until its environment is destructed.

+ This is an opaque type and values of it can only by used either as + arguments to API functions or as return values from NIFs. All + ERL_NIF_TERMs belong to an environment + (ErlNifEnv). + A term cannot be destructed individually, it is valid until its + environment is destructed.

- ErlNifEnv + ErlNifEnv -

ErlNifEnv represents an environment that can host Erlang terms. - All terms in an environment are valid as long as the environment is valid. - ErlNifEnv is an opaque type and pointers to it can only be passed - on to API functions. There are two types of environments; process - bound and process independent.

-

A process bound environment is passed as the first argument to all NIFs. - All function arguments passed to a NIF will belong to that environment. - The return value from a NIF must also be a term belonging to the same - environment. - In addition a process bound environment contains transient information - about the calling Erlang process. The environment is only valid in the - thread where it was supplied as argument until the NIF returns. It is - thus useless and dangerous to store pointers to process bound - environments between NIF calls.

-

A process independent environment is created by calling - enif_alloc_env. It can be - used to store terms between NIF calls and to send terms with - enif_send. A process - independent environment with all its terms is valid until you explicitly - invalidates it with enif_free_env - or enif_send.

+

ErlNifEnv represents an environment that can host Erlang + terms. All terms in an environment are valid as long as the + environment is valid. ErlNifEnv is an opaque type; pointers to + it can only be passed on to API functions. Two types of environments + exist:

+ + Process-bound environment + +

Passed as the first argument to all NIFs. All function arguments + passed to a NIF belong to that environment. The return value from + a NIF must also be a term belonging to the same environment.

+

A process-bound environment contains transient information + about the calling Erlang process. The environment is only valid + in the thread where it was supplied as argument until the NIF + returns. It is thus useless and dangerous to store pointers to + process-bound environments between NIF calls.

+
+ Process-independent environment + +

Created by calling + enif_alloc_env. This environment can be + used to store terms between NIF calls and to send terms with + enif_send. A + process-independent environment with all its terms is valid until + you explicitly invalidate it with + enif_free_env + or enif_send.

+
+

All contained terms of a list/tuple/map must belong to the same - environment as the list/tuple/map itself. Terms can be copied between - environments with - enif_make_copy.

+ environment as the list/tuple/map itself. Terms can be copied between + environments with + enif_make_copy.

- ErlNifFunc - -

- + ErlNifFunc + + typedef struct { const char* name; unsigned arity; ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); unsigned flags; -} ErlNifFunc; - -

Describes a NIF by its name, arity and implementation. - fptr is a pointer to the function that implements the - NIF. The argument argv of a NIF will contain the - function arguments passed to the NIF and argc is the - length of the array, i.e. the function arity. argv[N-1] - will thus denote the Nth argument to the NIF. Note that the - argc argument allows for the same C function to - implement several Erlang functions with different arity (but - same name probably). For a regular NIF, flags is 0 (and - so its value can be omitted for statically initialized ErlNifFunc - instances), or it can be used to indicate that the NIF is a dirty NIF that should be executed - on a dirty scheduler thread (note that the dirty NIF functionality - described here is experimental and that you have to enable - support for dirty schedulers when building OTP in order to try the - functionality out). If the dirty NIF is expected to be - CPU-bound, its flags field should be set to - ERL_NIF_DIRTY_JOB_CPU_BOUND, or for I/O-bound jobs, - ERL_NIF_DIRTY_JOB_IO_BOUND.

-

If one of the - ERL_NIF_DIRTY_JOB_*_BOUND flags is set, and the runtime - system has no support for dirty schedulers, the runtime system - will refuse to load the NIF library.

+} ErlNifFunc;
+

Describes a NIF by its name, arity, and implementation.

+ + fptr + +

A pointer to the function that implements the NIF.

+
+ argv + +

Contains the function arguments passed to the NIF.

+
+ argc + +

The array length, that is, the function arity. argv[N-1] + thus denotes the Nth argument to the NIF. Notice that the argument + argc allows for the same C function to implement several + Erlang functions with different arity (but probably with the same + name).

+
+ flags + +

Is 0 for a regular NIF (and so its value can be omitted + for statically initialized ErlNifFunc instances).

+

flags can be used to indicate that the NIF is a + dirty NIF that is to be + executed on a dirty scheduler thread.

+

The dirty NIF functionality described here is + experimental. You have to enable support for dirty + schedulers when building OTP to try out the functionality.

+

If the dirty NIF is expected to be CPU-bound, its flags + field is to be set to ERL_NIF_DIRTY_JOB_CPU_BOUND or + ERL_NIF_DIRTY_JOB_IO_BOUND.

+ +

If one of the ERL_NIF_DIRTY_JOB_*_BOUND flags is set, + and the runtime system has no support for dirty schedulers, + the runtime system refuses to load the NIF library.

+
+
+
- ErlNifBinary - -

- + ErlNifBinary + + typedef struct { unsigned size; unsigned char* data; -} ErlNifBinary; - +} ErlNifBinary;

ErlNifBinary contains transient information about an inspected binary term. data is a pointer to a buffer of size bytes with the raw content of the binary.

-

Note that ErlNifBinary is a semi-opaque type and you are +

Notice that ErlNifBinary is a semi-opaque type and you are only allowed to read fields size and data.

- - ErlNifBinaryToTerm + ErlNifBinaryToTerm -

An enumeration of the options that can be given to - enif_binary_to_term. - For default behavior, use the value 0.

- - ERL_NIF_BIN2TERM_SAFE -

Use this option when receiving data from untrusted sources.

-
+

An enumeration of the options that can be specified to + + enif_binary_to_term. + For default behavior, use value 0.

+

When receiving data from untrusted sources, use option + ERL_NIF_BIN2TERM_SAFE.

- - ErlNifPid - -

ErlNifPid is a process identifier (pid). In contrast to - pid terms (instances of ERL_NIF_TERM), ErlNifPid's are self - contained and not bound to any - environment. ErlNifPid - is an opaque type.

-
- ErlNifPort - -

ErlNifPort is a port identifier. In contrast to - port id terms (instances of ERL_NIF_TERM), ErlNifPort's are self - contained and not bound to any - environment. ErlNifPort - is an opaque type.

-
- - ErlNifResourceType - -

Each instance of ErlNifResourceType represent a class of - memory managed resource objects that can be garbage collected. + ErlNifPid + +

A process identifier (pid). In contrast to pid terms (instances of + ERL_NIF_TERM), ErlNifPids are self-contained and not + bound to any environment. + ErlNifPid is an opaque type.

+
+ ErlNifPort + +

A port identifier. In contrast to port ID terms (instances of + ERL_NIF_TERM), ErlNifPorts are self-contained and not + bound to any environment. + ErlNifPort is an opaque type.

+
+ ErlNifResourceType + +

Each instance of ErlNifResourceType represents a class of + memory-managed resource objects that can be garbage collected. Each resource type has a unique name and a destructor function that is called when objects of its type are released.

-
- ErlNifResourceDtor - -

- -typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); - -

The function prototype of a resource destructor function.

-
- ErlNifCharEncoding - -

- + + ErlNifResourceDtor + + +typedef void ErlNifResourceDtor(ErlNifEnv* env, void* obj); +

The function prototype of a resource destructor function.

+
+ ErlNifCharEncoding + + typedef enum { ERL_NIF_LATIN1 -}ErlNifCharEncoding; - -

The character encoding used in strings and atoms. The only - supported encoding is currently ERL_NIF_LATIN1 for - iso-latin-1 (8-bit ascii).

-
- ErlNifSysInfo - -

Used by enif_system_info - to return information about the runtime system. Contains currently - the exact same content as ErlDrvSysInfo.

-
- ErlNifSInt64 -

A native signed 64-bit integer type.

- ErlNifUInt64 -

A native unsigned 64-bit integer type.

- - ErlNifTime +}ErlNifCharEncoding;
+

The character encoding used in strings and atoms. The only + supported encoding is ERL_NIF_LATIN1 for + ISO Latin-1 (8-bit ASCII).

+
+ ErlNifSysInfo + +

Used by + enif_system_info to return information about the + runtime system. Contains the same content as + + ErlDrvSysInfo.

+
+ ErlNifSInt64 + +

A native signed 64-bit integer type.

+
+ ErlNifUInt64 + +

A native unsigned 64-bit integer type.

+
+ ErlNifTime

A signed 64-bit integer type for representation of time.

- ErlNifTimeUnit + ErlNifTimeUnit

An enumeration of time units supported by the NIF API:

- - ERL_NIF_SEC -

Seconds

- ERL_NIF_MSEC -

Milliseconds

- ERL_NIF_USEC -

Microseconds

- ERL_NIF_NSEC -

Nanoseconds

-
+ + ERL_NIF_SEC + Seconds + ERL_NIF_MSEC + Milliseconds + ERL_NIF_USEC + Microseconds + ERL_NIF_NSEC + Nanoseconds +
- - ErlNifUniqueInteger + ErlNifUniqueInteger

An enumeration of the properties that can be requested from - enif_unique_integer. - For default properties, use the value 0.

+ + enif_unique_integer. + For default properties, use value 0.

- ERL_NIF_UNIQUE_POSITIVE -

Return only positive integers

- ERL_NIF_UNIQUE_MONOTONIC -

Return only - strictly - monotonically increasing integer corresponding to creation time

-
+ ERL_NIF_UNIQUE_POSITIVE + +

Return only positive integers.

+
+ ERL_NIF_UNIQUE_MONOTONIC + +

Return only + strictly monotonically increasing integer corresponding + to creation time.

+
+
-
void *enif_alloc(size_t size) - Allocate dynamic memory -

Allocate memory of size bytes. Return NULL if allocation failed.

+ Allocate dynamic memory. + +

Allocates memory of size bytes.

+

Returns NULL if the allocation fails.

+
- intenif_alloc_binary(size_t size, ErlNifBinary* bin) - Create a new binary -

Allocate a new binary of size size - bytes. Initialize the structure pointed to by bin to - refer to the allocated binary. The binary must either be released by - enif_release_binary - or ownership transferred to an Erlang term with - enif_make_binary. - An allocated (and owned) ErlNifBinary can be kept between NIF - calls.

-

Return true on success or false if allocation failed.

+ int + enif_alloc_binary(size_t size, ErlNifBinary* bin) + + Create a new binary. + +

Allocates a new binary of size size bytes. + Initializes the structure pointed to by bin to + refer to the allocated binary. The binary must either be released by + + enif_release_binary + or ownership transferred to an Erlang term with + enif_make_binary. + An allocated (and owned) ErlNifBinary can be kept between NIF + calls.

+

Returns true on success, or false if allocation + fails.

ErlNifEnv *enif_alloc_env() - Create a new environment -

Allocate a new process independent environment. The environment can - be used to hold terms that is not bound to any process. Such terms can - later be copied to a process environment with - enif_make_copy - or be sent to a process as a message with enif_send.

-

Return pointer to the new environment.

-
-
- - - void *enif_alloc_resource(ErlNifResourceType* type, unsigned size) - Allocate a memory managed resource object -

Allocate a memory managed resource object of type type and size size bytes.

-
- - - size_tenif_binary_to_term(ErlNifEnv *env, const unsigned char* data, size_t size, ERL_NIF_TERM *term, ErlNifBinaryToTerm opts) - Create a term from the external format - -

Create a term that is the result of decoding the binary data - at data, which must be encoded according to the Erlang external term format. - No more than size bytes are read from data. Argument opts - correspond to the second argument to - erlang:binary_to_term/2, and must be either 0 or - ERL_NIF_BIN2TERM_SAFE.

-

On success, store the resulting term at *term and return - the actual number of bytes read. Return zero if decoding fails or if opts - is invalid.

-

See also: - ErlNifBinaryToTerm, - erlang:binary_to_term/2 and - enif_term_to_binary. -

-
+ Create a new environment. + +

Allocates a new process-independent environment. The environment can + be used to hold terms that are not bound to any process. Such terms + can later be copied to a process environment with + enif_make_copy or + be sent to a process as a message with + enif_send.

+

Returns pointer to the new environment.

+
- - voidenif_clear_env(ErlNifEnv* env) - Clear an environment for reuse -

Free all terms in an environment and clear it for reuse. The environment must - have been allocated with enif_alloc_env. -

+ void *enif_alloc_resource(ErlNifResourceType* + type, unsigned size) + Allocate a memory-managed resource object. + +

Allocates a memory-managed resource object of type type and + size size bytes.

+
- - intenif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs) - Compare two terms -

Return an integer less than, equal to, or greater than - zero if lhs is found, respectively, to be less than, - equal, or greater than rhs. Corresponds to the Erlang - operators ==, /=, =<, <, - >= and > (but not =:= or =/=).

+ size_tenif_binary_to_term(ErlNifEnv *env, + const unsigned char* data, size_t size, ERL_NIF_TERM *term, + ErlNifBinaryToTerm opts) + Create a term from the external format. + +

Creates a term that is the result of decoding the binary data at + data, which must be encoded according to the Erlang external + term format. No more than size bytes are read from data. + Argument opts corresponds to the second argument to + + erlang:binary_to_term/2 and must be either 0 + or ERL_NIF_BIN2TERM_SAFE.

+

On success, stores the resulting term at *term and returns + the number of bytes read. Returns 0 if decoding fails or if + opts is invalid.

+

See also + ErlNifBinaryToTerm, + + erlang:binary_to_term/2, and + + enif_term_to_binary.

+
- voidenif_cond_broadcast(ErlNifCond *cnd) - -

Same as erl_drv_cond_broadcast. -

+ voidenif_clear_env(ErlNifEnv* env) + + Clear an environment for reuse. + +

Frees all terms in an environment and clears it for reuse. + The environment must have been allocated with + enif_alloc_env.

+
- ErlNifCond *enif_cond_create(char *name) - -

Same as erl_drv_cond_create. -

+ int + enif_compare(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs) + + Compare two terms. + +

Returns an integer < 0 if lhs < rhs, + 0 if lhs = rhs, and > 0 if + lhs > rhs. Corresponds to the Erlang + operators ==, /=, =<, <, + >=, and > (but not =:= or + =/=).

+
- voidenif_cond_destroy(ErlNifCond *cnd) - -

Same as erl_drv_cond_destroy. -

+ void + enif_cond_broadcast(ErlNifCond *cnd) + + +

Same as + erl_drv_cond_broadcast.

+
- voidenif_cond_signal(ErlNifCond *cnd) - -

Same as erl_drv_cond_signal. -

+ ErlNifCond * + enif_cond_create(char *name) + + +

Same as + erl_drv_cond_create.

+
- voidenif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx) - -

Same as erl_drv_cond_wait. -

+ void + enif_cond_destroy(ErlNifCond *cnd) + + +

Same as + erl_drv_cond_destroy.

+
- intenif_consume_timeslice(ErlNifEnv *env, int percent) - -

Give the runtime system a hint about how much CPU time the current NIF call has consumed - since last hint, or since the start of the NIF if no previous hint has been given. - The time is given as a percent of the timeslice that a process is allowed to execute Erlang - code until it may be suspended to give time for other runnable processes. - The scheduling timeslice is not an exact entity, but can usually be - approximated to about 1 millisecond.

-

Note that it is up to the runtime system to determine if and how to use this information. - Implementations on some platforms may use other means in order to determine consumed - CPU time. Lengthy NIFs should regardless of this frequently call enif_consume_timeslice - in order to determine if it is allowed to continue execution or not.

+ void + enif_cond_signal(ErlNifCond *cnd) + + +

Same as + erl_drv_cond_signal.

+
+
-

Returns 1 if the timeslice is exhausted, or 0 otherwise. If 1 is returned the NIF should return - as soon as possible in order for the process to yield.

-

Argument percent must be an integer between 1 and 100. This function - must only be called from a NIF-calling thread and argument env must be - the environment of the calling process.

-

This function is provided to better support co-operative scheduling, improve system responsiveness, - and make it easier to prevent misbehaviors of the VM due to a NIF monopolizing a scheduler thread. - It can be used to divide length work into - a number of repeated NIF-calls without the need to create threads. - See also the warning text at the beginning of this document.

- + + void + enif_cond_wait(ErlNifCond *cnd, ErlNifMutex *mtx) + + + +

Same as + erl_drv_cond_wait.

+
+ + int + enif_consume_timeslice(ErlNifEnv *env, int percent) + + + +

Gives the runtime system a hint about how much CPU time the current + NIF call has consumed since the last hint, or since the start of the + NIF if no previous hint has been specified. The time is specified as a + percent of the timeslice that a process is allowed to execute + Erlang code until it can be suspended to give time for other runnable + processes. The scheduling timeslice is not an exact entity, but can + usually be approximated to about 1 millisecond.

+

Notice that it is up to the runtime system to determine if and how + to use this information. Implementations on some platforms can use + other means to determine consumed CPU time. Lengthy NIFs should + regardless of this frequently call enif_consume_timeslice to + determine if it is allowed to continue execution.

+

Argument percent must be an integer between 1 and 100. This + function must only be called from a NIF-calling thread, and argument + env must be the environment of the calling process.

+

Returns 1 if the timeslice is exhausted, otherwise 0. + If 1 is returned, the NIF is to return as soon as possible in + order for the process to yield.

+

This function is provided to better support co-operative scheduling, + improve system responsiveness, and make it easier to prevent + misbehaviors of the VM because of a NIF monopolizing a scheduler + thread. It can be used to divide + length work into a number of repeated NIF calls without the + need to create threads.

+

See also the warning text at + the beginning of this manual page.

+
+
- ErlNifTimeenif_convert_time_unit(ErlNifTime val, ErlNifTimeUnit from, ErlNifTimeUnit to) - Convert time unit of a time value + ErlNifTimeenif_convert_time_unit(ErlNifTime + val, ErlNifTimeUnit from, ErlNifTimeUnit to) + Convert time unit of a time value. - -

Arguments:

- - val - Value to convert time unit for. - from - Time unit of val. - to - Time unit of returned value. - -

Converts the val value of time unit from to - the corresponding value of time unit to. The result is - rounded using the floor function.

-

Returns ERL_NIF_TIME_ERROR if called with an invalid - time unit argument.

-

See also: - ErlNifTime and - ErlNifTimeUnit. -

+ +

Converts the val value of time unit from to + the corresponding value of time unit to. The result is + rounded using the floor function.

+ + val + Value to convert time unit for. + from + Time unit of val. + to + Time unit of returned value. + +

Returns ERL_NIF_TIME_ERROR if called with an invalid + time unit argument.

+

See also ErlNifTime + and + ErlNifTimeUnit.

- ERL_NIF_TERMenif_cpu_time(ErlNifEnv *) + ERL_NIF_TERM + enif_cpu_time(ErlNifEnv *) -

Returns the CPU time in the same format as erlang:timestamp(). - The CPU time is the time the current logical cpu has spent executing since - some arbitrary point in the past. - If the OS does not support fetching of this value enif_cpu_time - invokes enif_make_badarg. -

+

Returns the CPU time in the same format as + + erlang:timestamp(). + The CPU time is the time the current logical CPU has spent executing + since some arbitrary point in the past. If the OS does not support + fetching this value, enif_cpu_time invokes + + enif_make_badarg.

- intenif_equal_tids(ErlNifTid tid1, ErlNifTid tid2) - -

Same as erl_drv_equal_tids. -

+ int + enif_equal_tids(ErlNifTid tid1, ErlNifTid tid2) + + + +

Same as + erl_drv_equal_tids.

+
voidenif_free(void* ptr) - Free dynamic memory -

Free memory allocated by enif_alloc.

+ Free dynamic memory. + +

Frees memory allocated by + enif_alloc.

+
- voidenif_free_env(ErlNifEnv* env) - Free an environment allocated with enif_alloc_env -

Free an environment allocated with enif_alloc_env. - All terms created in the environment will be freed as well.

+ void + enif_free_env(ErlNifEnv* env) + Free an environment allocated with enif_alloc_env. + +

Frees an environment allocated with + enif_alloc_env. + All terms created in the environment are freed as well.

+
- intenif_get_atom(ErlNifEnv* env, ERL_NIF_TERM term, char* buf, unsigned size, ErlNifCharEncoding encode) - Get the text representation of an atom term -

Write a null-terminated string, in the buffer pointed to by - buf of size size, consisting of the string - representation of the atom term with encoding - encode. Return - the number of bytes written (including terminating null character) or 0 if - term is not an atom with maximum length of - size-1.

+ intenif_get_atom(ErlNifEnv* env, ERL_NIF_TERM + term, char* buf, unsigned size, ErlNifCharEncoding encode) + + Get the text representation of an atom term. + +

Writes a NULL-terminated string in the buffer pointed to by + buf of size size, consisting of the string + representation of the atom term with encoding + encode.

+

Returns the number of bytes written (including terminating + NULL character) or 0 if term is not an atom with + maximum length of size-1.

+
- intenif_get_atom_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode) - Get the length of atom term -

Set *len to the length (number of bytes excluding - terminating null character) of the atom term with encoding - encode. Return true on success or false if term is not an - atom.

+ intenif_get_atom_length(ErlNifEnv* env, + ERL_NIF_TERM term, unsigned* len, ErlNifCharEncoding encode) + + Get the length of atom term. + +

Sets *len to the length (number of bytes excluding + terminating NULL character) of the atom term with + encoding encode.

+

Returns true on success, or false if term is not + an atom.

+
- intenif_get_double(ErlNifEnv* env, ERL_NIF_TERM term, double* dp) - Read a floating-point number term -

Set *dp to the floating point value of - term. Return true on success or false if term is not a float.

+ intenif_get_double(ErlNifEnv* env, + ERL_NIF_TERM term, double* dp) + Read a floating-point number term. + +

Sets *dp to the floating-point value of term.

+

Returns true on success, or false if term is not + a float.

+
- intenif_get_int(ErlNifEnv* env, ERL_NIF_TERM term, int* ip) - Read an integer term -

Set *ip to the integer value of - term. Return true on success or false if term is not an - integer or is outside the bounds of type int.

+ intenif_get_int(ErlNifEnv* env, ERL_NIF_TERM + term, int* ip) + Read an integer term. + +

Sets *ip to the integer value of term.

+

Returns true on success, or false if term is not + an integer or is outside the bounds of type int.

+
- intenif_get_int64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifSInt64* ip) - Read a 64-bit integer term -

Set *ip to the integer value of - term. Return true on success or false if term is not an - integer or is outside the bounds of a signed 64-bit integer.

+ intenif_get_int64(ErlNifEnv* env, ERL_NIF_TERM + term, ErlNifSInt64* ip) + Read a 64-bit integer term. + +

Sets *ip to the integer value of term.

+

Returns true on success, or false if term is not + an integer or is outside the bounds of a signed 64-bit integer.

+
- intenif_get_local_pid(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPid* pid) - Read an local pid term -

If term is the pid of a node local process, initialize the - pid variable *pid from it and return true. Otherwise return false. - No check if the process is alive is done.

+ intenif_get_local_pid(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifPid* pid) + Read a local pid term. + +

If term is the pid of a node local process, this function + initializes the pid variable *pid from it and returns + true. Otherwise returns false. No check is done if the + process is alive.

+
- intenif_get_local_port(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifPort* port_id) - Read an local port term -

If term identifies a node local port, initialize the - port variable *port_id from it and return true. Otherwise return false. - No check if the port is alive is done.

+ intenif_get_local_port(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifPort* port_id) + Read a local port term. + +

If term identifies a node local port, this function + initializes the port variable *port_id from it and returns + true. Otherwise returns false. No check is done if the + port is alive.

+
- intenif_get_list_cell(ErlNifEnv* env, ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail) - Get head and tail from a list -

Set *head and *tail from - list and return true, or return false if list is not a - non-empty list.

+ intenif_get_list_cell(ErlNifEnv* env, + ERL_NIF_TERM list, ERL_NIF_TERM* head, ERL_NIF_TERM* tail) + + Get head and tail from a list. + +

Sets *head and *tail from list list.

+

Returns true on success, or false if the list is + empty.

+
- intenif_get_list_length(ErlNifEnv* env, ERL_NIF_TERM term, unsigned* len) - Get the length of list term -

Set *len to the length of list term and return true, - or return false if term is not a proper list.

+ intenif_get_list_length(ErlNifEnv* env, + ERL_NIF_TERM term, unsigned* len) + Get the length of list term. + +

Sets *len to the length of list term.

+

Returns true on success, or false if term is + not a proper list.

+
- intenif_get_long(ErlNifEnv* env, ERL_NIF_TERM term, long int* ip) - Read an long integer term -

Set *ip to the long integer value of term and - return true, or return false if term is not an integer or is - outside the bounds of type long int.

+ intenif_get_long(ErlNifEnv* env, ERL_NIF_TERM + term, long int* ip) + Read a long integer term. + +

Sets *ip to the long integer value of term.

+

Returns true on success, or false if term is + not an integer or is outside the bounds of type long int.

+
- intenif_get_map_size(ErlNifEnv* env, ERL_NIF_TERM term, size_t *size) - Read the size of a map term -

Set *size to the number of key-value pairs in the map term and - return true, or return false if term is not a map.

+ intenif_get_map_size(ErlNifEnv* env, + ERL_NIF_TERM term, size_t *size) + Read the size of a map term. + +

Sets *size to the number of key-value pairs in the map + term.

+

Returns true on success, or false if term is + not a map.

+
- intenif_get_map_value(ErlNifEnv* env, ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value) - Get the value of a key in a map -

Set *value to the value associated with key in the - map map and return true. Return false if map is not a map - or if map does not contain key.

+ intenif_get_map_value(ErlNifEnv* env, + ERL_NIF_TERM map, ERL_NIF_TERM key, ERL_NIF_TERM* value) + + Get the value of a key in a map. + +

Sets *value to the value associated with key in the + map map.

+

Returns true on success, or false if map is not + a map or if map does not contain key.

+
- - intenif_get_resource(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifResourceType* type, void** objp) - Get the pointer to a resource object -

Set *objp to point to the resource object referred to by term.

-

Return true on success or false if term is not a handle to a resource object - of type type.

+ + + intenif_get_resource(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifResourceType* type, void** objp) + + Get the pointer to a resource object. + +

Sets *objp to point to the resource object referred to by + term.

+

Returns true on success, or false if term is + not a handle to a resource object of type type.

+
- intenif_get_string(ErlNifEnv* env, - ERL_NIF_TERM list, char* buf, unsigned size, - ErlNifCharEncoding encode) - Get a C-string from a list -

Write a null-terminated string, in the buffer pointed to by - buf with size size, consisting of the characters - in the string list. The characters are written using encoding - encode. - Return the number of bytes written (including terminating null - character), or -size if the string was truncated due to - buffer space, or 0 if list is not a string that can be - encoded with encode or if size was less than 1. - The written string is always null-terminated unless buffer - size is less than 1.

+ intenif_get_string(ErlNifEnv* env, + ERL_NIF_TERM list, char* buf, unsigned size, + ErlNifCharEncoding encode) + Get a C-string from a list. + +

Writes a NULL-terminated string in the buffer pointed to by + buf with size size, consisting of the characters + in the string list. The characters are written using encoding + encode.

+

Returns one of the following:

+ + The number of bytes written (including terminating NULL + character) + -size if the string was truncated because of buffer + space + 0 if list is not a string that can be encoded + with encode or if size was < 1. + +

The written string is always NULL-terminated, unless buffer + size is < 1.

+
- intenif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM term, int* arity, const ERL_NIF_TERM** array) - Inspect the elements of a tuple -

If term is a tuple, set *array to point - to an array containing the elements of the tuple and set - *arity to the number of elements. Note that the array - is read-only and (*array)[N-1] will be the Nth element of - the tuple. *array is undefined if the arity of the tuple - is zero.

Return true on success or false if term is not a - tuple.

+ intenif_get_tuple(ErlNifEnv* env, ERL_NIF_TERM + term, int* arity, const ERL_NIF_TERM** array) + Inspect the elements of a tuple. + +

If term is a tuple, this function sets *array to point + to an array containing the elements of the tuple, and sets + *arity to the number of elements. Notice that the array + is read-only and (*array)[N-1] is the Nth element of + the tuple. *array is undefined if the arity of the tuple + is zero.

+

Returns true on success, or false if term is + not a tuple.

+
- intenif_get_uint(ErlNifEnv* env, ERL_NIF_TERM term, unsigned int* ip) - Read an unsigned integer term -

Set *ip to the unsigned integer value of term and - return true, or return false if term is not an unsigned integer or - is outside the bounds of type unsigned int.

+ intenif_get_uint(ErlNifEnv* env, ERL_NIF_TERM + term, unsigned int* ip) + Read an unsigned integer term. + +

Sets *ip to the unsigned integer value of term.

+

Returns true on success, or false if term is + not an unsigned integer or is outside the bounds of type + unsigned int.

+
- intenif_get_uint64(ErlNifEnv* env, ERL_NIF_TERM term, ErlNifUInt64* ip) - Read an unsigned 64-bit integer term -

Set *ip to the unsigned integer value of term and - return true, or return false if term is not an unsigned integer or - is outside the bounds of an unsigned 64-bit integer.

+ intenif_get_uint64(ErlNifEnv* env, + ERL_NIF_TERM term, ErlNifUInt64* ip) + Read an unsigned 64-bit integer term. + +

Sets *ip to the unsigned integer value of term.

+

Returns true on success, or false if term is + not an unsigned integer or is outside the bounds of an unsigned + 64-bit integer.

+
- intenif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM term, unsigned long* ip) - Read an unsigned integer term -

Set *ip to the unsigned long integer value of term - and return true, or return false if term is not an unsigned integer or is - outside the bounds of type unsigned long.

+ intenif_get_ulong(ErlNifEnv* env, ERL_NIF_TERM + term, unsigned long* ip) + Read an unsigned integer term. + +

Sets *ip to the unsigned long integer value of + term.

+

Returns true on success, or false if term is + not an unsigned integer or is outside the bounds of type + unsigned long.

+
- intenif_getenv(const char* key, char* value, size_t *value_size) - Get the value of an environment variable -

Same as erl_drv_getenv.

+ intenif_getenv(const char* key, char* value, + size_t *value_size) + Get the value of an environment variable. + +

Same as + erl_drv_getenv.

+
- intenif_has_pending_exception(ErlNifEnv* env, ERL_NIF_TERM* reason) - Check if an exception has been raised -

Return true if a pending exception is associated - with the environment env. If reason is a null pointer, ignore it. - Otherwise, if there's a pending exception associated with env, set the ERL_NIF_TERM - to which reason points to the value of the exception's term. For example, if - enif_make_badarg is called to set a - pending badarg exception, a subsequent call to enif_has_pending_exception(env, &reason) - will set reason to the atom badarg, then return true.

-

See also: enif_make_badarg - and enif_raise_exception.

+ intenif_has_pending_exception(ErlNifEnv* env, + ERL_NIF_TERM* reason) + Check if an exception has been raised. + +

Returns true if a pending exception is associated with the + environment env. If reason is a NULL pointer, + ignore it. Otherwise, if a pending exception associated with + env exists, set ERL_NIF_TERM to which reason + points to the value of the exception's term. For example, if + + enif_make_badarg is called to set a pending + badarg exception, a later call to + enif_has_pending_exception(env, &reason) sets + reason to the atom badarg, then return true.

+

See also + enif_make_badarg and + + enif_raise_exception.

- intenif_inspect_binary(ErlNifEnv* env, ERL_NIF_TERM bin_term, ErlNifBinary* bin) - Inspect the content of a binary -

Initialize the structure pointed to by bin with - information about the binary term - bin_term. Return true on success or false if bin_term is not a binary.

+ intenif_inspect_binary(ErlNifEnv* env, + ERL_NIF_TERM bin_term, ErlNifBinary* bin) + Inspect the content of a binary. + +

Initializes the structure pointed to by bin with information + about binary term bin_term.

+

Returns true on success, or false if bin_term + is not a binary.

+
- intenif_inspect_iolist_as_binary(ErlNifEnv* - env, ERL_NIF_TERM term, ErlNifBinary* bin) - - Inspect the content of an iolist -

Initialize the structure pointed to by bin with one - continuous buffer with the same byte content as iolist. As with - inspect_binary, the data pointed to by bin is transient and does - not need to be released. Return true on success or false if iolist is not an - iolist.

+ intenif_inspect_iolist_as_binary(ErlNifEnv* + env, ERL_NIF_TERM term, ErlNifBinary* bin) + Inspect the content of an iolist. + +

Initializes the structure pointed to by bin with a + continuous buffer with the same byte content as iolist. As + with inspect_binary, the data pointed to by bin is + transient and does not need to be released.

+

Returns true on success, or false if iolist is + not an iolist.

- intenif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is an atom -

Return true if term is an atom.

+ int + enif_is_atom(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is an atom. + +

Returns true if term is an atom.

+
- intenif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a binary -

Return true if term is a binary

+ int + enif_is_binary(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a binary. + +

Returns true if term is a binary.

+
- intenif_is_current_process_alive(ErlNifEnv* env) - Determine if currently executing process is alive or not. -

Return true if currently executing process is currently alive; otherwise - false.

-

This function can only be used from a NIF-calling thread, and with an - environment corresponding to currently executing processes.

+ int + enif_is_current_process_alive(ErlNifEnv* env) + + Determine if currently executing process is alive. + +

Returns true if the currently executing process is currently + alive, otherwise false.

+

This function can only be used from a NIF-calling thread, and with + an environment corresponding to currently executing processes.

+
- intenif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is an empty list -

Return true if term is an empty list.

+ intenif_is_empty_list(ErlNifEnv* env, + ERL_NIF_TERM term) + Determine if a term is an empty list. + +

Returns true if term is an empty list.

+
- intenif_is_exception(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is an exception + intenif_is_exception(ErlNifEnv* env, + ERL_NIF_TERM term) + Determine if a term is an exception. -

Return true if term is an exception.

+

Return true if term is an exception.

+
- intenif_is_fun(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a fun -

Return true if term is a fun.

+ intenif_is_fun(ErlNifEnv* env, ERL_NIF_TERM + term) + Determine if a term is a fun. + +

Returns true if term is a fun.

+
- intenif_is_identical(ERL_NIF_TERM lhs, ERL_NIF_TERM rhs) - Erlang operator =:= -

Return true if the two terms are identical. Corresponds to the - Erlang operators =:= and - =/=.

+ intenif_is_identical(ERL_NIF_TERM lhs, + ERL_NIF_TERM rhs) + Erlang operator =:=. + +

Returns true if the two terms are identical. Corresponds to + the Erlang operators =:= and =/=.

+
- intenif_is_list(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a list -

Return true if term is a list.

+ int + enif_is_list(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a list. + +

Returns true if term is a list.

+
- intenif_is_map(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a map -

Return true if term is a map, false otherwise.

+ intenif_is_map(ErlNifEnv* env, ERL_NIF_TERM + term) + Determine if a term is a map. + +

Returns true if term is a map, otherwise + false.

+
- intenif_is_number(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a number (integer or float) -

Return true if term is a number.

+ intenif_is_number(ErlNifEnv* env, ERL_NIF_TERM + term) + Determine if a term is a number (integer or float). + +

Returns true if term is a number.

+
- intenif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a pid -

Return true if term is a pid.

+ int + enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a pid. + +

Returns true if term is a pid.

+
- intenif_is_port(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a port -

Return true if term is a port.

+ int + enif_is_port(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a port. + +

Returns true if term is a port.

+
- intenif_is_port_alive(ErlNifEnv* env, ErlNifPort *port_id) - Determine if a local port is alive or not. -

Return true if port_id is currently alive.

-

This function is only thread-safe when the emulator with SMP support is used. - It can only be used in a non-SMP emulator from a NIF-calling thread.

+ intenif_is_port_alive(ErlNifEnv* env, + ErlNifPort *port_id) + Determine if a local port is alive. + +

Returns true if port_id is alive.

+

This function is only thread-safe when the emulator with SMP support + is used. It can only be used in a non-SMP emulator from a NIF-calling + thread.

+
- intenif_is_process_alive(ErlNifEnv* env, ErlNifPid *pid) - Determine if a local process is alive or not. -

Return true if pid is currently alive.

-

This function is only thread-safe when the emulator with SMP support is used. - It can only be used in a non-SMP emulator from a NIF-calling thread.

+ intenif_is_process_alive(ErlNifEnv* env, + ErlNifPid *pid) + Determine if a local process is alive. + +

Returns true if pid is alive.

+

This function is only thread-safe when the emulator with SMP support + is used. It can only be used in a non-SMP emulator from a NIF-calling + thread.

+
- intenif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a reference -

Return true if term is a reference.

+ int + enif_is_ref(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a reference. + +

Returns true if term is a reference.

+
- intenif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term) - Determine if a term is a tuple -

Return true if term is a tuple.

+ int + enif_is_tuple(ErlNifEnv* env, ERL_NIF_TERM term) + + Determine if a term is a tuple. + +

Returns true if term is a tuple.

+
- intenif_keep_resource(void* obj) - Add a reference to a resource object -

Add a reference to resource object obj obtained from - enif_alloc_resource. - Each call to enif_keep_resource for an object must be balanced by - a call to enif_release_resource - before the object will be destructed.

+ int + enif_keep_resource(void* obj) + + Add a reference to a resource object. + +

Adds a reference to resource object obj obtained from + + enif_alloc_resource. Each call to + enif_keep_resource for an object must be balanced by a call to + + enif_release_resource + before the object is destructed.

+
- ERL_NIF_TERMenif_make_atom(ErlNifEnv* env, const char* name) - Create an atom term -

Create an atom term from the null-terminated C-string name - with iso-latin-1 encoding. If the length of name exceeds the maximum length - allowed for an atom (255 characters), enif_make_atom invokes - enif_make_badarg. -

+ ERL_NIF_TERM + enif_make_atom(ErlNifEnv* env, const char* name) + + Create an atom term. + +

Creates an atom term from the NULL-terminated C-string + name with ISO Latin-1 encoding. If the length of name + exceeds the maximum length allowed for an atom (255 characters), + enif_make_atom invokes + enif_make_badarg.

+
- ERL_NIF_TERMenif_make_atom_len(ErlNifEnv* env, const char* name, size_t len) - Create an atom term -

Create an atom term from the string name with length len. - Null-characters are treated as any other characters. If len is greater than the maximum length - allowed for an atom (255 characters), enif_make_atom invokes - enif_make_badarg. -

+ ERL_NIF_TERMenif_make_atom_len(ErlNifEnv* env, + const char* name, size_t len) + Create an atom term. + +

Create an atom term from the string name with length + len. NULL characters are treated as any other + characters. If len exceeds the maximum length + allowed for an atom (255 characters), enif_make_atom invokes + + enif_make_badarg.

+
- ERL_NIF_TERMenif_make_badarg(ErlNifEnv* env) - Make a badarg exception -

Make a badarg exception to be returned from a NIF, and associate - it with the environment env. Once a NIF or any function - it calls invokes enif_make_badarg, the runtime ensures that a - badarg exception is raised when the NIF returns, even if the NIF - attempts to return a non-exception term instead. - The return value from enif_make_badarg may be used only as the - return value from the NIF that invoked it (directly or indirectly) - or be passed to - enif_is_exception, but - not to any other NIF API function.

-

See also: enif_has_pending_exception - and enif_raise_exception. -

-

In earlier versions (older than erts-7.0, OTP 18) the return value - from enif_make_badarg had to be returned from the NIF. This - requirement is now lifted as the return value from the NIF is ignored - if enif_make_badarg has been invoked.

+ ERL_NIF_TERM + enif_make_badarg(ErlNifEnv* env) + Make a badarg exception. + +

Makes a badarg exception to be returned from a NIF, and + associates it with environment env. Once a NIF or any function + it calls invokes enif_make_badarg, the runtime ensures that a + badarg exception is raised when the NIF returns, even if the + NIF attempts to return a non-exception term instead.

+

The return value from enif_make_badarg can be used only as + the return value from the NIF that invoked it (directly or indirectly) + or be passed to + enif_is_exception, but not to any other NIF API + function.

+

See also + enif_has_pending_exception and + + enif_raise_exception.

+ +

Before ERTS 7.0 (Erlang/OTP 18), the return value + from enif_make_badarg had to be returned from the NIF. This + requirement is now lifted as the return value from the NIF is + ignored if enif_make_badarg has been invoked.

+
+
- ERL_NIF_TERMenif_make_binary(ErlNifEnv* env, ErlNifBinary* bin) - Make a binary term -

Make a binary term from bin. Any ownership of - the binary data will be transferred to the created term and - bin should be considered read-only for the rest of the NIF - call and then as released.

+ ERL_NIF_TERM + enif_make_binary(ErlNifEnv* env, ErlNifBinary* bin) + + Make a binary term. + +

Makes a binary term from bin. Any ownership of + the binary data is transferred to the created term and + bin is to be considered read-only for the rest of the NIF + call and then as released.

+
- ERL_NIF_TERMenif_make_copy(ErlNifEnv* dst_env, ERL_NIF_TERM src_term) - Make a copy of a term -

Make a copy of term src_term. The copy will be created in - environment dst_env. The source term may be located in any - environment.

+ ERL_NIF_TERMenif_make_copy(ErlNifEnv* dst_env, + ERL_NIF_TERM src_term) + Make a copy of a term. + +

Makes a copy of term src_term. The copy is created in + environment dst_env. The source term can be located in any + environment.

+
- ERL_NIF_TERMenif_make_double(ErlNifEnv* env, double d) - Create a floating-point term -

Create a floating-point term from a double. If the double argument is - not finite or is NaN, enif_make_double invokes - enif_make_badarg. -

+ ERL_NIF_TERM + enif_make_double(ErlNifEnv* env, double d) + Create a floating-point term. + +

Creates a floating-point term from a double. If argument + double is not finite or is NaN, enif_make_double + invokes + enif_make_badarg.

+
- intenif_make_existing_atom(ErlNifEnv* env, const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding encode) - Create an existing atom term -

Try to create the term of an already existing atom from - the null-terminated C-string name with encoding - encode. If the atom - already exists store the term in *atom and return true, otherwise - return false. If the length of name exceeds the maximum length - allowed for an atom (255 characters), enif_make_existing_atom - returns false.

+ intenif_make_existing_atom(ErlNifEnv* env, + const char* name, ERL_NIF_TERM* atom, ErlNifCharEncoding + encode) + Create an existing atom term. + +

Tries to create the term of an already existing atom from + the NULL-terminated C-string name with encoding + encode.

+

If the atom already exists, this function stores the term in + *atom and returns true, otherwise false. + Also returns false if the length of name exceeds the + maximum length allowed for an atom (255 characters).

+
- intenif_make_existing_atom_len(ErlNifEnv* env, const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding encoding) - Create an existing atom term -

Try to create the term of an already existing atom from the - string name with length len and encoding - encode. Null-characters - are treated as any other characters. If the atom already exists store the term - in *atom and return true, otherwise return false. If len is greater - than the maximum length allowed for an atom (255 characters), - enif_make_existing_atom_len returns false.

+ intenif_make_existing_atom_len(ErlNifEnv* env, + const char* name, size_t len, ERL_NIF_TERM* atom, ErlNifCharEncoding + encoding) + Create an existing atom term. + +

Tries to create the term of an already existing atom from the + string name with length len and encoding + encode. NULL + characters are treated as any other characters.

+

If the atom already exists, this function stores the term in + *atom and returns true, otherwise false. + Also returns false if len exceeds the maximum length + allowed for an atom (255 characters).

+
- - ERL_NIF_TERMenif_make_int(ErlNifEnv* env, int i) - Create an integer term -

Create an integer term.

+ ERL_NIF_TERM + enif_make_int(ErlNifEnv* env, int i) + Create an integer term. + +

Creates an integer term.

+
- ERL_NIF_TERMenif_make_int64(ErlNifEnv* env, ErlNifSInt64 i) - Create an integer term -

Create an integer term from a signed 64-bit integer.

+ ERL_NIF_TERM + enif_make_int64(ErlNifEnv* env, ErlNifSInt64 i) + + Create an integer term. + +

Creates an integer term from a signed 64-bit integer.

+
- ERL_NIF_TERMenif_make_list(ErlNifEnv* env, unsigned cnt, ...) - Create a list term -

Create an ordinary list term of length cnt. Expects - cnt number of arguments (after cnt) of type ERL_NIF_TERM as the - elements of the list. An empty list is returned if cnt is 0.

+ ERL_NIF_TERM + enif_make_list(ErlNifEnv* env, unsigned cnt, ...) + + Create a list term. + +

Creates an ordinary list term of length cnt. Expects + cnt number of arguments (after cnt) of type + ERL_NIF_TERM as the elements of the list.

+

Returns an empty list if cnt is 0.

+
- ERL_NIF_TERMenif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1) - ERL_NIF_TERMenif_make_list2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2) - ERL_NIF_TERMenif_make_list3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3) - ERL_NIF_TERMenif_make_list4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4) - ERL_NIF_TERMenif_make_list5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5) - ERL_NIF_TERMenif_make_list6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6) - ERL_NIF_TERMenif_make_list7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7) - ERL_NIF_TERMenif_make_list8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8) - ERL_NIF_TERMenif_make_list9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9) - Create a list term -

Create an ordinary list term with length indicated by the - function name. Prefer these functions (macros) over the variadic - enif_make_list to get a compile time error if the number of - arguments does not match.

+ ERL_NIF_TERM + enif_make_list1(ErlNifEnv* env, ERL_NIF_TERM e1) + + ERL_NIF_TERMenif_make_list2(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2) + ERL_NIF_TERMenif_make_list3(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3) + ERL_NIF_TERMenif_make_list4(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4) + ERL_NIF_TERMenif_make_list5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5) + ERL_NIF_TERMenif_make_list6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6) + ERL_NIF_TERMenif_make_list7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7) + ERL_NIF_TERMenif_make_list8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8) + ERL_NIF_TERMenif_make_list9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9) + Create a list term. + +

Creates an ordinary list term with length indicated by the + function name. Prefer these functions (macros) over the variadic + enif_make_list to get a compile-time error if the number of + arguments does not match.

+
- ERL_NIF_TERMenif_make_list_cell(ErlNifEnv* env, ERL_NIF_TERM head, ERL_NIF_TERM tail) - Create a list cell -

Create a list cell [head | tail].

+ ERL_NIF_TERMenif_make_list_cell(ErlNifEnv* + env, ERL_NIF_TERM head, ERL_NIF_TERM tail) + Create a list cell. + +

Creates a list cell [head | tail].

+
- ERL_NIF_TERMenif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt) - Create a list term from an array -

Create an ordinary list containing the elements of array arr - of length cnt. An empty list is returned if cnt is 0.

+ ERL_NIF_TERM + enif_make_list_from_array(ErlNifEnv* env, const ERL_NIF_TERM + arr[], unsigned cnt) + Create a list term from an array. + +

Creates an ordinary list containing the elements of array arr + of length cnt.

+

Returns an empty list if cnt is 0.

+
- ERL_NIF_TERMenif_make_long(ErlNifEnv* env, long int i) - Create an integer term from a long int -

Create an integer term from a long int.

+ ERL_NIF_TERM + enif_make_long(ErlNifEnv* env, long int i) + Create an integer term from a long int. + +

Creates an integer term from a long int.

+
- intenif_make_map_put(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, ERL_NIF_TERM* map_out) - Insert key-value pair in map -

Make a copy of map map_in and insert key with - value. If key already exists in map_in, the old - associated value is replaced by value. If successful set - *map_out to the new map and return true. Return false if - map_in is not a map.

-

The map_in term must belong to the environment env.

+ intenif_make_map_put(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM value, + ERL_NIF_TERM* map_out) + Insert key-value pair in map. + +

Makes a copy of map map_in and inserts key with + value. If key already exists in map_in, the old + associated value is replaced by value.

+

If successful, this function sets *map_out to the new map and + returns true. Returns false if map_in is not a + map.

+

The map_in term must belong to environment env.

+
- intenif_make_map_remove(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out) - Remove key from map -

If map map_in contains key, make a copy of - map_in in *map_out and remove key and associated - value. If map map_in does not contain key, set - *map_out to map_in. Return true for success or false if - map_in is not a map.

-

The map_in term must belong to the environment env.

+ intenif_make_map_remove(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM* map_out) + + Remove key from map. + +

If map map_in contains key, this function makes a copy + of map_in in *map_out, and removes key and the + associated value. If map map_in does not contain key, + *map_out is set to map_in.

+

Returns true on success, or false if map_in is + not a map.

+

The map_in term must belong to environment env.

+
- intenif_make_map_update(ErlNifEnv* env, ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, ERL_NIF_TERM* map_out) - Replace value for key in map -

Make a copy of map map_in and replace the old associated - value for key with new_value. If successful set - *map_out to the new map and return true. Return false if - map_in is not a map or if it does no contain key.

-

The map_in term must belong to the environment env.

+ intenif_make_map_update(ErlNifEnv* env, + ERL_NIF_TERM map_in, ERL_NIF_TERM key, ERL_NIF_TERM new_value, + ERL_NIF_TERM* map_out) + Replace value for key in map. + +

Makes a copy of map map_in and replace the old associated + value for key with new_value.

+

If successful, this function sets *map_out to the new map and + returns true. Returns false if map_in is not a + map or if it does not contain key.

+

The map_in term must belong to environment env.

+
- unsigned char *enif_make_new_binary(ErlNifEnv* env, size_t size, ERL_NIF_TERM* termp) - Allocate and create a new binary term -

Allocate a binary of size size bytes and create an owning - term. The binary data is mutable until the calling NIF returns. This is a - quick way to create a new binary without having to use - ErlNifBinary. The drawbacks are - that the binary can not be kept between NIF calls and it can not be - reallocated.

Return a pointer to the raw binary data and set - *termp to the binary term.

+ unsigned char *enif_make_new_binary(ErlNifEnv* + env, size_t size, ERL_NIF_TERM* termp) + Allocate and create a new binary term. + +

Allocates a binary of size size bytes and creates an owning + term. The binary data is mutable until the calling NIF returns. + This is a quick way to create a new binary without having to use + ErlNifBinary. + The drawbacks are that the binary cannot be kept between NIF calls + and it cannot be reallocated.

+

Returns a pointer to the raw binary data and sets + *termp to the binary term.

+
- ERL_NIF_TERMenif_make_new_map(ErlNifEnv* env) - Make an empty map term -

Make an empty map term.

+ ERL_NIF_TERM + enif_make_new_map(ErlNifEnv* env) + Make an empty map term. + +

Makes an empty map term.

+
- ERL_NIF_TERMenif_make_pid(ErlNifEnv* env, const ErlNifPid* pid) - Make a pid term -

Make a pid term from *pid.

+ ERL_NIF_TERM + enif_make_pid(ErlNifEnv* env, const ErlNifPid* pid) + + Make a pid term. + +

Makes a pid term from *pid.

+
- ERL_NIF_TERMenif_make_ref(ErlNifEnv* env) - Create a reference -

Create a reference like erlang:make_ref/0.

+ ERL_NIF_TERM + enif_make_ref(ErlNifEnv* env) + Create a reference. + +

Creates a reference like + erlang:make_ref/0.

+
- ERL_NIF_TERMenif_make_resource(ErlNifEnv* env, void* obj) - Create an opaque handle to a resource object -

Create an opaque handle to a memory managed resource object - obtained by enif_alloc_resource. - No ownership transfer is done, as the resource object still needs to be released by - enif_release_resource, - but note that the call to enif_release_resource can occur - immediately after obtaining the term from enif_make_resource, - in which case the resource object will be deallocated when the - term is garbage collected. See the - example of creating and - returning a resource object for more details.

-

Note that the only defined behaviour of using a resource term in - an Erlang program is to store it and send it between processes on the - same node. Other operations such as matching or term_to_binary - will have unpredictable (but harmless) results.

+ ERL_NIF_TERM + enif_make_resource(ErlNifEnv* env, void* obj) + + Create an opaque handle to a resource object. + +

Creates an opaque handle to a memory-managed resource object + obtained by + enif_alloc_resource. No ownership transfer is done, + as the resource object still needs to be released by + + enif_release_resource. However, notice that the call + to enif_release_resource can occur immediately after obtaining + the term from enif_make_resource, in which case the resource + object is deallocated when the term is garbage collected. For more + details, see the example of + creating and returning a resource object in the User's + Guide.

+

Notice that the only defined behavior of using a resource term in + an Erlang program is to store it and send it between processes on the + same node. Other operations, such as matching or + term_to_binary, have unpredictable (but harmless) results.

+
- ERL_NIF_TERMenif_make_resource_binary(ErlNifEnv* env, void* obj, const void* data, size_t size) - Create a custom binary term -

Create a binary term that is memory managed by a resource object - obj obtained by enif_alloc_resource. - The returned binary term will consist of size bytes pointed to - by data. This raw binary data must be kept readable and unchanged - until the destructor of the resource is called. The binary data may be - stored external to the resource object in which case it is the responsibility - of the destructor to release the data.

-

Several binary terms may be managed by the same resource object. The - destructor will not be called until the last binary is garbage collected. - This can be useful as a way to return different parts of a larger binary - buffer.

-

As with enif_make_resource, - no ownership transfer is done. The resource still needs to be released with - enif_release_resource.

+ ERL_NIF_TERM + enif_make_resource_binary(ErlNifEnv* env, void* obj, const + void* data, size_t size) + Create a custom binary term. + +

Creates a binary term that is memory-managed by a resource object + obj obtained by + enif_alloc_resource. The returned binary term + consists of size bytes pointed to by data. This raw + binary data must be kept readable and unchanged until the destructor + of the resource is called. The binary data can be stored external to + the resource object, in which case the destructor is responsible + for releasing the data.

+

Several binary terms can be managed by the same resource object. The + destructor is not called until the last binary is garbage collected. + This can be useful to return different parts of a larger binary + buffer.

+

As with + enif_make_resource, no ownership transfer is done. + The resource still needs to be released with + + enif_release_resource.

- intenif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, ERL_NIF_TERM *list_out) - Create the reverse of a list -

Set *list_out to the reverse list of the list list_in and return true, - or return false if list_in is not a list. This function should only be used on - short lists as a copy will be created of the list which will not be released until after the - nif returns.

-

The list_in term must belong to the environment env.

+ int + enif_make_reverse_list(ErlNifEnv* env, ERL_NIF_TERM list_in, + ERL_NIF_TERM *list_out) + Create the reverse of a list. + +

Sets *list_out to the reverse list of the list list_in + and returns true, or returns false if list_in is + not a list.

+

This function is only to be used on short lists, as a copy is + created of the list, which is not released until after the NIF + returns.

+

The list_in term must belong to environment env.

+
- ERL_NIF_TERMenif_make_string(ErlNifEnv* env, const char* string, ErlNifCharEncoding encoding) - Create a string -

Create a list containing the characters of the - null-terminated string string with encoding encoding.

+ ERL_NIF_TERMenif_make_string(ErlNifEnv* env, + const char* string, ErlNifCharEncoding encoding) + Create a string. + +

Creates a list containing the characters of the + NULL-terminated string string with encoding + encoding.

+
- ERL_NIF_TERMenif_make_string_len(ErlNifEnv* env, const char* string, size_t len, ErlNifCharEncoding encoding) - Create a string -

Create a list containing the characters of the string string with - length len and encoding encoding. - Null-characters are treated as any other characters.

+ ERL_NIF_TERMenif_make_string_len(ErlNifEnv* + env, const char* string, size_t len, ErlNifCharEncoding + encoding) + Create a string. + +

Creates a list containing the characters of the string string + with length len and encoding + encoding. + NULL characters are treated as any other characters.

+
- ERL_NIF_TERMenif_make_sub_binary(ErlNifEnv* - env, ERL_NIF_TERM bin_term, size_t pos, size_t size) - Make a subbinary term -

Make a subbinary of binary bin_term, starting at - zero-based position pos with a length of size bytes. - bin_term must be a binary or bitstring and - pos+size must be less or equal to the number of whole - bytes in bin_term.

+ ERL_NIF_TERMenif_make_sub_binary(ErlNifEnv* + env, ERL_NIF_TERM bin_term, size_t pos, size_t size) + Make a subbinary term. + +

Makes a subbinary of binary bin_term, starting at + zero-based position pos with a length of size bytes. + bin_term must be a binary or bitstring. pos+size must + be less or equal to the number of whole bytes in bin_term.

+
- ERL_NIF_TERMenif_make_tuple(ErlNifEnv* env, unsigned cnt, ...) - Create a tuple term -

Create a tuple term of arity cnt. Expects - cnt number of arguments (after cnt) of type ERL_NIF_TERM as the - elements of the tuple.

+ ERL_NIF_TERMenif_make_tuple(ErlNifEnv* env, + unsigned cnt, ...) + Creates a tuple term. + +

Creates a tuple term of arity cnt. Expects cnt number + of arguments (after cnt) of type ERL_NIF_TERM as the + elements of the tuple.

+
- ERL_NIF_TERMenif_make_tuple1(ErlNifEnv* env, ERL_NIF_TERM e1) - ERL_NIF_TERMenif_make_tuple2(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2) - ERL_NIF_TERMenif_make_tuple3(ErlNifEnv* env, ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3) - ERL_NIF_TERMenif_make_tuple4(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4) - ERL_NIF_TERMenif_make_tuple5(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5) - ERL_NIF_TERMenif_make_tuple6(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6) - ERL_NIF_TERMenif_make_tuple7(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7) - ERL_NIF_TERMenif_make_tuple8(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8) - ERL_NIF_TERMenif_make_tuple9(ErlNifEnv* env, ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9) - Create a tuple term -

Create a tuple term with length indicated by the - function name. Prefer these functions (macros) over the variadic - enif_make_tuple to get a compile time error if the number of - arguments does not match.

+ ERL_NIF_TERMenif_make_tuple1(ErlNifEnv* env, + ERL_NIF_TERM e1) + ERL_NIF_TERMenif_make_tuple2(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2) + ERL_NIF_TERMenif_make_tuple3(ErlNifEnv* env, + ERL_NIF_TERM e1, ERL_NIF_TERM e2, ERL_NIF_TERM e3) + ERL_NIF_TERMenif_make_tuple4(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e4) + ERL_NIF_TERMenif_make_tuple5(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e5) + ERL_NIF_TERMenif_make_tuple6(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e6) + ERL_NIF_TERMenif_make_tuple7(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e7) + ERL_NIF_TERMenif_make_tuple8(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e8) + ERL_NIF_TERMenif_make_tuple9(ErlNifEnv* env, + ERL_NIF_TERM e1, ..., ERL_NIF_TERM e9) + Create a tuple term. + +

Creates a tuple term with length indicated by the + function name. Prefer these functions (macros) over the variadic + enif_make_tuple to get a compile-time error if the number of + arguments does not match.

+
- ERL_NIF_TERMenif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM arr[], unsigned cnt) - Create a tuple term from an array -

Create a tuple containing the elements of array arr - of length cnt.

+ ERL_NIF_TERM + enif_make_tuple_from_array(ErlNifEnv* env, const ERL_NIF_TERM + arr[], unsigned cnt) + Create a tuple term from an array. + +

Creates a tuple containing the elements of array arr + of length cnt.

+
- ERL_NIF_TERMenif_make_uint(ErlNifEnv* env, unsigned int i) - Create an unsigned integer term -

Create an integer term from an unsigned int.

+ ERL_NIF_TERM + enif_make_uint(ErlNifEnv* env, unsigned int i) + + Create an unsigned integer term. + +

Creates an integer term from an unsigned int.

+
- ERL_NIF_TERMenif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i) - Create an unsigned integer term -

Create an integer term from an unsigned 64-bit integer.

+ ERL_NIF_TERM + enif_make_uint64(ErlNifEnv* env, ErlNifUInt64 i) + + Create an unsigned integer term. + +

Creates an integer term from an unsigned 64-bit integer.

+
- ERL_NIF_TERMenif_make_ulong(ErlNifEnv* env, unsigned long i) - Create an integer term from an unsigned long int -

Create an integer term from an unsigned long int.

+ ERL_NIF_TERM + enif_make_ulong(ErlNifEnv* env, unsigned long i) + + Create an integer term from an unsigned long int. + +

Creates an integer term from an unsigned long int.

+
- ERL_NIF_TERMenif_make_unique_integer(ErlNifEnv *env, ErlNifUniqueInteger properties) + ERL_NIF_TERMenif_make_unique_integer(ErlNifEnv + *env, ErlNifUniqueInteger properties) -

Returns a unique integer with the same properties as given by erlang:unique_integer/1.

+

Returns a unique integer with the same properties as specified by + + erlang:unique_integer/1.

env is the environment to create the integer in.

-

- ERL_NIF_UNIQUE_POSITIVE and ERL_NIF_UNIQUE_MONOTONIC can - be passed as the second argument to change the properties of the - integer returned. It is possible to combine them by or:ing the - two values together. -

-

See also: - ErlNifUniqueInteger. -

+

ERL_NIF_UNIQUE_POSITIVE and ERL_NIF_UNIQUE_MONOTONIC + can be passed as the second argument to change the properties of the + integer returned. They can be combined by OR:ing the two values + together.

+

See also + ErlNifUniqueInteger.

- intenif_map_iterator_create(ErlNifEnv *env, ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry entry) - Create a map iterator -

Create an iterator for the map map by initializing the - structure pointed to by iter. The entry argument determines - the start position of the iterator: ERL_NIF_MAP_ITERATOR_FIRST or - ERL_NIF_MAP_ITERATOR_LAST. Return true on success or false if - map is not a map.

-

A map iterator is only useful during the lifetime of the environment - env that the map belongs to. The iterator must be destroyed by - calling - enif_map_iterator_destroy.

- + intenif_map_iterator_create(ErlNifEnv *env, + ERL_NIF_TERM map, ErlNifMapIterator *iter, ErlNifMapIteratorEntry + entry) + Create a map iterator. + +

Creates an iterator for the map map by initializing the + structure pointed to by iter. Argument entry determines + the start position of the iterator: ERL_NIF_MAP_ITERATOR_FIRST + or ERL_NIF_MAP_ITERATOR_LAST.

+

Returns true on success, or false if map is not a + map.

+

A map iterator is only useful during the lifetime of environment + env that the map belongs to. The iterator must be + destroyed by calling + enif_map_iterator_destroy:

+ ERL_NIF_TERM key, value; ErlNifMapIterator iter; enif_map_iterator_create(env, my_map, &iter, ERL_NIF_MAP_ITERATOR_FIRST); @@ -1646,643 +2069,712 @@ while (enif_map_iterator_get_pair(env, &iter, &key, &value)) { do_something(key,value); enif_map_iterator_next(env, &iter); } -enif_map_iterator_destroy(env, &iter); - -

The key-value pairs of a map have no defined iteration - order. The only guarantee is that the iteration order of a single map - instance is preserved during the lifetime of the environment that the map - belongs to.

-
+enif_map_iterator_destroy(env, &iter);
+ +

The key-value pairs of a map have no defined iteration order. + The only guarantee is that the iteration order of a single map + instance is preserved during the lifetime of the environment that + the map belongs to.

+
- voidenif_map_iterator_destroy(ErlNifEnv *env, ErlNifMapIterator *iter) - Destroy a map iterator + voidenif_map_iterator_destroy(ErlNifEnv *env, + ErlNifMapIterator *iter) + Destroy a map iterator. -

Destroy a map iterator created by - enif_map_iterator_create. -

+

Destroys a map iterator created by + + enif_map_iterator_create.

- intenif_map_iterator_get_pair(ErlNifEnv *env, ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM *value) - Get key and value at current map iterator position + intenif_map_iterator_get_pair(ErlNifEnv *env, + ErlNifMapIterator *iter, ERL_NIF_TERM *key, ERL_NIF_TERM + *value) + Get key and value at current map iterator position. -

Get key and value terms at current map iterator position. - On success set *key and *value and return true. - Return false if the iterator is positioned at head (before first entry) - or tail (beyond last entry).

+

Gets key and value terms at the current map iterator position.

+

On success, sets *key and *value and returns + true. Returns false if the iterator is positioned at + head (before first entry) or tail (beyond last entry).

- intenif_map_iterator_is_head(ErlNifEnv *env, ErlNifMapIterator *iter) - Check if map iterator is positioned before first + intenif_map_iterator_is_head(ErlNifEnv *env, + ErlNifMapIterator *iter) + Check if map iterator is positioned before first. -

Return true if map iterator iter is positioned - before first entry.

+

Returns true if map iterator iter is positioned + before the first entry.

- intenif_map_iterator_is_tail(ErlNifEnv *env, ErlNifMapIterator *iter) - Check if map iterator is positioned after last + intenif_map_iterator_is_tail(ErlNifEnv *env, + ErlNifMapIterator *iter) + Check if map iterator is positioned after last. -

Return true if map iterator iter is positioned - after last entry.

+

Returns true if map iterator iter is positioned + after the last entry.

- intenif_map_iterator_next(ErlNifEnv *env, ErlNifMapIterator *iter) - Increment map iterator to point to next entry + intenif_map_iterator_next(ErlNifEnv *env, + ErlNifMapIterator *iter) + Increment map iterator to point to next entry. -

Increment map iterator to point to next key-value entry. - Return true if the iterator is now positioned at a valid key-value entry, - or false if the iterator is positioned at the tail (beyond the last - entry).

+

Increments map iterator to point to the next key-value entry.

+

Returns true if the iterator is now positioned at a valid + key-value entry, or false if the iterator is positioned at + the tail (beyond the last entry).

- intenif_map_iterator_prev(ErlNifEnv *env, ErlNifMapIterator *iter) - Decrement map iterator to point to previous entry + intenif_map_iterator_prev(ErlNifEnv *env, + ErlNifMapIterator *iter) + Decrement map iterator to point to previous entry. -

Decrement map iterator to point to previous key-value entry. - Return true if the iterator is now positioned at a valid key-value entry, - or false if the iterator is positioned at the head (before the first - entry).

+

Decrements map iterator to point to the previous key-value entry.

+

Returns true if the iterator is now positioned at a valid + key-value entry, or false if the iterator is positioned at + the head (before the first entry).

- ErlNifTimeenif_monotonic_time(ErlNifTimeUnit time_unit) - Get Erlang Monotonic Time + ErlNifTime + enif_monotonic_time(ErlNifTimeUnit time_unit) + + Get Erlang monotonic time. - -

Arguments:

- - time_unit - Time unit of returned value. - -

- Returns the current - Erlang - monotonic time. Note that it is not uncommon with - negative values. -

-

Returns ERL_NIF_TIME_ERROR if called with an invalid - time unit argument, or if called from a thread that is not a - scheduler thread.

-

See also: - ErlNifTime and - ErlNifTimeUnit. -

+ +

Returns the current + + Erlang monotonic time. Notice that it is not uncommon with + negative values.

+

time_unit is the time unit of the returned value.

+

Returns ERL_NIF_TIME_ERROR if called with an invalid time + unit argument, or if called from a thread that is not a scheduler + thread.

+

See also ErlNifTime + and ErlNifTimeUnit. +

ErlNifMutex * - enif_mutex_create(char *name) - - -

Same as erl_drv_mutex_create. -

+ enif_mutex_create(char *name) + + +

Same as + erl_drv_mutex_create.

void - enif_mutex_destroy(ErlNifMutex *mtx) - - -

Same as erl_drv_mutex_destroy. -

+ enif_mutex_destroy(ErlNifMutex *mtx) + + +

Same as + erl_drv_mutex_destroy.

void - enif_mutex_lock(ErlNifMutex *mtx) - - -

Same as erl_drv_mutex_lock. -

+ enif_mutex_lock(ErlNifMutex *mtx) + + +

Same as + erl_drv_mutex_lock.

- - int + int enif_mutex_trylock(ErlNifMutex *mtx) - - -

Same as erl_drv_mutex_trylock. -

+ + +

Same as + erl_drv_mutex_trylock.

void - enif_mutex_unlock(ErlNifMutex *mtx) - - -

Same as erl_drv_mutex_unlock. -

+ enif_mutex_unlock(ErlNifMutex *mtx)
+ + +

Same as + erl_drv_mutex_unlock.

ERL_NIF_TERM - enif_now_time(ErlNifEnv *env) - - -

Retuns an erlang:now() timestamp. - The enif_now_time function is deprecated.

+ enif_now_time(ErlNifEnv *env) + + +

Returns an + erlang:now() time stamp.

+

This function is deprecated.

ErlNifResourceType * - enif_open_resource_type(ErlNifEnv* env, - const char* module_str, const char* name, - ErlNifResourceDtor* dtor, ErlNifResourceFlags flags, ErlNifResourceFlags* tried) - Create or takeover a resource type - -

Create or takeover a resource type identified by the string - name and give it the destructor function pointed to by dtor. - Argument flags can have the following values:

- - ERL_NIF_RT_CREATE - Create a new resource type that does not already exist. - ERL_NIF_RT_TAKEOVER - Open an existing resource type and take over ownership of all its instances. - The supplied destructor dtor will be called both for existing instances - as well as new instances not yet created by the calling NIF library. - -

The two flag values can be combined with bitwise-or. The name of the - resource type is local to the calling module. Argument module_str - is not (yet) used and must be NULL. The dtor may be NULL - in case no destructor is needed.

-

On success, return a pointer to the resource type and *tried - will be set to either ERL_NIF_RT_CREATE or - ERL_NIF_RT_TAKEOVER to indicate what was actually done. - On failure, return NULL and set *tried to flags. - It is allowed to set tried to NULL.

-

Note that enif_open_resource_type is only allowed to be called in the three callbacks - load, reload - and upgrade.

+ enif_open_resource_type(ErlNifEnv* env, const char* + module_str, const char* name, ErlNifResourceDtor* dtor, + ErlNifResourceFlags flags, ErlNifResourceFlags* tried) + + Create or takeover a resource type. + +

Creates or takes over a resource type identified by the string + name and gives it the destructor function pointed to by + dtor. + Argument flags can have the following values:

+ + ERL_NIF_RT_CREATE + Creates a new resource type that does not already exist. + ERL_NIF_RT_TAKEOVER + Opens an existing resource type and takes over ownership of all + its instances. The supplied destructor dtor is called both + for existing instances and new instances not yet created by the + calling NIF library. + +

The two flag values can be combined with bitwise OR. The resource + type name is local to the calling module. Argument module_str + is not (yet) used and must be NULL. dtor can be + NULL if no destructor is needed.

+

On success, the function returns a pointer to the resource type and + *tried is set to either ERL_NIF_RT_CREATE or + ERL_NIF_RT_TAKEOVER to indicate what was done. On failure, + returns NULL and sets *tried to flags. + It is allowed to set tried to NULL.

+

Notice that enif_open_resource_type is only allowed to be + called in the three callbacks + load, + reload, and + upgrade.

- int - enif_port_command(ErlNifEnv* env, const ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg) - Send a port_command to to_port - -

This function works the same as erlang:port_command/2 - except that it is always completely asynchronous.

- - env - The environment of the calling process. May not be NULL. - *to_port - The port id of the receiving port. The port id should refer to a - port on the local node. - msg_env - The environment of the message term. Can be a process - independent environment allocated with - enif_alloc_env or NULL. - msg - The message term to send. The same limitations apply as on the - payload to erlang:port_command/2. - -

Using a msg_env of NULL is an optimization which groups together - calls to enif_alloc_env, enif_make_copy, enif_port_command - and enif_free_env into one call. This optimization is only usefull - when a majority of the terms are to be copied from env to the msg_env.

-

This function return true if the command was successfully sent; otherwise, - false. The call may return false if it detects that the command failed for some - reason. For example, *to_port does not refer to a local port, if currently - executing process, i.e. the sender, is not alive, or if msg is invalid.

-

See also: enif_get_local_port.

+ intenif_port_command(ErlNifEnv* env, const + ErlNifPort* to_port, ErlNifEnv *msg_env, ERL_NIF_TERM msg) + + Send a port_command to to_port. + +

Works as + erlang:port_command/2, + except that it is always completely asynchronous.

+ + env + The environment of the calling process. Must not be + NULL. + *to_port + The port ID of the receiving port. The port ID is to refer to a + port on the local node. + msg_env + The environment of the message term. Can be a process-independent + environment allocated with + enif_alloc_env or NULL. + msg + The message term to send. The same limitations apply as on the + payload to + erlang:port_command/2. + +

Using a msg_env of NULL is an optimization, which + groups together calls to enif_alloc_env, enif_make_copy, + enif_port_command, and enif_free_env into one call. + This optimization is only useful when a majority of the terms are to + be copied from env to msg_env.

+

Returns true if the command is successfully sent. Returns + false if the command fails, for example:

+ + *to_port does not refer to a local port. + The currently executing process (that is, the sender) is not + alive. + msg is invalid. + +

See also + enif_get_local_port.

void * - enif_priv_data(ErlNifEnv* env) - Get the private data of a NIF library + enif_priv_data(ErlNifEnv* env) + Get the private data of a NIF library. -

Return the pointer to the private data that was set by load, - reload or upgrade.

-

Was previously named enif_get_data.

+

Returns the pointer to the private data that was set by + load, + reload, or + upgrade.

+

Was previously named enif_get_data.

- ERL_NIF_TERM - enif_raise_exception(ErlNifEnv* env, ERL_NIF_TERM reason) - Raise a NIF error exception + ERL_NIF_TERMenif_raise_exception(ErlNifEnv* + env, ERL_NIF_TERM reason) + Raise a NIF error exception. -

Create an error exception with the term reason to be returned from a NIF, - and associate it with the environment env. Once a NIF or any function it calls - invokes enif_raise_exception, the runtime ensures that the exception it creates - is raised when the NIF returns, even if the NIF attempts to return a non-exception - term instead. The return value from enif_raise_exception may be used only as - the return value from the NIF that invoked it (directly or indirectly) or be passed - to enif_is_exception, but - not to any other NIF API function.

-

See also: enif_has_pending_exception - and enif_make_badarg.

+

Creates an error exception with the term reason to be + returned from a NIF, and associates it with environment env. + Once a NIF or any function it calls invokes + enif_raise_exception, the runtime ensures that the exception + it creates is raised when the NIF returns, even if the NIF attempts + to return a non-exception term instead.

+

The return value from enif_raise_exception can only be used + as the return value from the NIF that invoked it (directly or + indirectly) or be passed to + enif_is_exception, but not to any other NIF API + function.

+

See also + enif_has_pending_exception and + + enif_make_badarg.

int - enif_realloc_binary(ErlNifBinary* bin, size_t size) - Change the size of a binary + enif_realloc_binary(ErlNifBinary* bin, size_t size) + + Change the size of a binary. -

Change the size of a binary bin. The source binary - may be read-only, in which case it will be left untouched and - a mutable copy is allocated and assigned to *bin. Return true on success, - false if memory allocation failed.

+

Changes the size of a binary bin. The source binary + can be read-only, in which case it is left untouched and + a mutable copy is allocated and assigned to *bin.

+

Returns true on success, or false if memory allocation + failed.

void - enif_release_binary(ErlNifBinary* bin) - Release a binary + enif_release_binary(ErlNifBinary* bin) + Release a binary. -

Release a binary obtained from enif_alloc_binary.

+

Releases a binary obtained from + + enif_alloc_binary.

void - enif_release_resource(void* obj) - Release a resource object + enif_release_resource(void* obj) + Release a resource object. -

Remove a reference to resource object objobtained from - enif_alloc_resource. - The resource object will be destructed when the last reference is removed. - Each call to enif_release_resource must correspond to a previous - call to enif_alloc_resource or - enif_keep_resource. - References made by enif_make_resource - can only be removed by the garbage collector.

+

Removes a reference to resource object objobtained from + + enif_alloc_resource. + The resource object is destructed when the last reference is removed. + Each call to enif_release_resource must correspond to a + previous call to enif_alloc_resource or + + enif_keep_resource. + References made by + enif_make_resource + can only be removed by the garbage collector.

ErlNifRWLock * - enif_rwlock_create(char *name) - - -

Same as erl_drv_rwlock_create. -

+ enif_rwlock_create(char *name) + + +

Same as + erl_drv_rwlock_create.

void - enif_rwlock_destroy(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_destroy. -

+ enif_rwlock_destroy(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_destroy.

void - enif_rwlock_rlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_rlock. -

+ enif_rwlock_rlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_rlock.

void - enif_rwlock_runlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_runlock. -

+ enif_rwlock_runlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_runlock.

void - enif_rwlock_rwlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_rwlock. -

+ enif_rwlock_rwlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_rwlock.

void - enif_rwlock_rwunlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_rwunlock. -

+ enif_rwlock_rwunlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_rwunlock.

int - enif_rwlock_tryrlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_tryrlock. -

+ enif_rwlock_tryrlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_tryrlock.

int - enif_rwlock_tryrwlock(ErlNifRWLock *rwlck) - - -

Same as erl_drv_rwlock_tryrwlock. -

+ enif_rwlock_tryrwlock(ErlNifRWLock *rwlck) + + +

Same as + erl_drv_rwlock_tryrwlock.

- ERL_NIF_TERM - enif_schedule_nif(ErlNifEnv* env, const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM argv[]) - Schedule a NIF for execution - -

Schedule NIF fp to execute. This function allows an application to break up long-running - work into multiple regular NIF calls or to schedule a dirty NIF - to execute on a dirty scheduler thread (note that the dirty NIF functionality described here is - experimental and that you have to enable support for dirty schedulers when building OTP in - order to try the functionality out).

-

The fun_name argument provides a name for the NIF being scheduled for execution. If it cannot - be converted to an atom, enif_schedule_nif returns a badarg exception.

-

The flags argument must be set to 0 for a regular NIF, or if the emulator was built the - experimental dirty scheduler support enabled, flags can be set to either ERL_NIF_DIRTY_JOB_CPU_BOUND - if the job is expected to be CPU-bound, or ERL_NIF_DIRTY_JOB_IO_BOUND for jobs that will - be I/O-bound. If dirty scheduler threads are not available in the emulator, a try to schedule such a job - will result in a badarg exception.

- -

The argc and argv arguments can either be the originals passed into the calling NIF, or - they can be values created by the calling NIF.

-

The calling NIF must use the return value of enif_schedule_nif as its own return value.

-

Be aware that enif_schedule_nif, as its name implies, only schedules the - NIF for future execution. The calling NIF does not block waiting for the scheduled NIF to - execute and return, which means that the calling NIF can't expect to receive the scheduled NIF + ERL_NIF_TERMenif_schedule_nif(ErlNifEnv* env, + const char* fun_name, int flags, ERL_NIF_TERM (*fp)(ErlNifEnv* env, int + argc, const ERL_NIF_TERM argv[]), int argc, const ERL_NIF_TERM + argv[]) + Schedule a NIF for execution. + +

Schedules NIF fp to execute. This function allows an + application to break up long-running work into multiple regular NIF + calls or to schedule a + dirty NIF to execute on a dirty scheduler thread.

+

The dirty NIF functionality described here is + experimental. You have to enable support for dirty + schedulers when building OTP to try out the functionality.

+ + fun_name + +

Provides a name for the NIF that is scheduled for execution. + If it cannot be converted to an atom, enif_schedule_nif + returns a badarg exception.

+
+ flags + +

Must be set to 0 for a regular NIF. If the emulator was + built with the experimental dirty scheduler support enabled, + flags can be set to either + ERL_NIF_DIRTY_JOB_CPU_BOUND if the job is expected to be + CPU-bound, or ERL_NIF_DIRTY_JOB_IO_BOUND for + jobs that will be I/O-bound. If dirty scheduler threads are not + available in the emulator, an attempt to schedule such a job + results in a badarg exception.

+
+ argc and argv + +

Can either be the originals passed into the calling NIF, + or can be values created by the calling NIF.

+
+
+

The calling NIF must use the return value of + enif_schedule_nif as its own return value.

+

Be aware that enif_schedule_nif, as its name implies, only + schedules the NIF for future execution. The calling NIF does not + block waiting for the scheduled NIF to execute and return. This means + that the calling NIF cannot expect to receive the scheduled NIF return value and use it for further operations.

ErlNifPid * - enif_self(ErlNifEnv* caller_env, ErlNifPid* pid) - Get the pid of the calling process + enif_self(ErlNifEnv* caller_env, ErlNifPid* pid) + + Get the pid of the calling process. -

Initialize the pid variable *pid to represent the - calling process. Return pid.

+

Initializes the pid variable *pid to represent the + calling process.

+

Returns pid.

- int - enif_send(ErlNifEnv* env, ErlNifPid* to_pid, ErlNifEnv* msg_env, ERL_NIF_TERM msg) - Send a message to a process - -

Send a message to a process.

- - env - The environment of the calling process. Must be NULL if and - only if calling from a created thread. - *to_pid - The pid of the receiving process. The pid should refer to a process on the local node. - msg_env - The environment of the message term. Must be a process - independent environment allocated with - enif_alloc_env or NULL. - msg - The message term to send. - -

Return true if the message was successfully sent; otherwise, false. The send - operation will fail if *to_pid does not refer to an alive local process, - or if currently executing process, i.e. the sender, is not alive.

-

The message environment msg_env with all its terms (including - msg) will be invalidated by a successful call to enif_send. The environment - should either be freed with enif_free_env - of cleared for reuse with enif_clear_env.

-

If msg_env is set to NULL the msg term is copied and - the original term and its environemt is still valid after the call.

-

This function is only thread-safe when the emulator with SMP support is used. - It can only be used in a non-SMP emulator from a NIF-calling thread.

-

Passing msg_env as NULL is only supported since - erts-8.0 (OTP 19).

+ intenif_send(ErlNifEnv* env, ErlNifPid* to_pid, + ErlNifEnv* msg_env, ERL_NIF_TERM msg) + Send a message to a process. + +

Sends a message to a process.

+ + env + The environment of the calling process. Must be NULL + only if calling from a created thread. + *to_pid + The pid of the receiving process. The pid is to refer to a + process on the local node. + msg_env + The environment of the message term. Must be a + process-independent environment allocated with + enif_alloc_env + or NULL. + msg + The message term to send. + +

Returns true if the message is successfully sent. Returns + false if the send operation fails, that is:

+ + *to_pid does not refer to an alive local process. + The currently executing process (that is, the sender) is not + alive. + +

The message environment msg_env with all its terms (including + msg) is invalidated by a successful call to enif_send. + The environment is to either be freed with + + enif_free_env of cleared for reuse with + enif_clear_env.

+

If msg_env is set to NULL, the msg term is + copied and the original term and its environemt is still valid after + the call.

+

This function is only thread-safe when the emulator with SMP support + is used. It can only be used in a non-SMP emulator from a NIF-calling + thread.

+ +

Passing msg_env as NULL is only supported as from + ERTS 8.0 (Erlang/OTP 19).

+
unsigned - enif_sizeof_resource(void* obj) - Get the byte size of a resource object + enif_sizeof_resource(void* obj) + Get the byte size of a resource object. -

Get the byte size of a resource object obj obtained by - enif_alloc_resource.

+

Gets the byte size of resource object obj obtained by + + enif_alloc_resource.

- int - enif_snprintf(char *str, size_t size, const char *format, ...) - Format strings and Erlang terms + intenif_snprintf(char *str, size_t size, const + char *format, ...) + Format strings and Erlang terms. -

Similar to snprintf but this format string also accepts "%T" which formats Erlang terms. -

+

Similar to snprintf but this format string also accepts + "%T", which formats Erlang terms.

- void - enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size) - Get information about the Erlang runtime system + voidenif_system_info(ErlNifSysInfo + *sys_info_ptr, size_t size) + Get information about the Erlang runtime system. -

Same as driver_system_info. -

+

Same as + driver_system_info.

- int - enif_term_to_binary(ErlNifEnv *env, ERL_NIF_TERM term, ErlNifBinary *bin) - Convert a term to the external format - -

Allocates a new binary with enif_alloc_binary - and stores the result of encoding term according to the Erlang external term format.

-

Returns true on success or false if allocation failed.

-

See also: - erlang:term_to_binary/1 and - enif_binary_to_term. -

-
+ intenif_term_to_binary(ErlNifEnv *env, + ERL_NIF_TERM term, ErlNifBinary *bin) + Convert a term to the external format. + +

Allocates a new binary with + enif_alloc_binary and stores the result of encoding + term according to the Erlang external term format.

+

Returns true on success, or false if the allocation + fails.

+

See also + erlang:term_to_binary/1 and + + enif_binary_to_term.

+
- int - enif_thread_create(char *name,ErlNifTid *tid,void * (*func)(void *),void *args,ErlNifThreadOpts *opts) - - -

Same as erl_drv_thread_create. -

+ intenif_thread_create(char *name,ErlNifTid + *tid,void * (*func)(void *),void *args,ErlNifThreadOpts + *opts) + + +

Same as + erl_drv_thread_create.

void - enif_thread_exit(void *resp) - - -

Same as erl_drv_thread_exit. -

+ enif_thread_exit(void *resp) + + +

Same as + erl_drv_thread_exit.

int - enif_thread_join(ErlNifTid, void **respp) - - -

Same as erl_drv_thread_join . -

+ enif_thread_join(ErlNifTid, void **respp) + + +

Same as + erl_drv_thread_join.

ErlNifThreadOpts * - enif_thread_opts_create(char *name) - - -

Same as erl_drv_thread_opts_create. -

+ enif_thread_opts_create(char *name) + + +

Same as + erl_drv_thread_opts_create.

void - enif_thread_opts_destroy(ErlNifThreadOpts *opts) - - -

Same as erl_drv_thread_opts_destroy. -

+ enif_thread_opts_destroy(ErlNifThreadOpts *opts) + + + +

Same as + erl_drv_thread_opts_destroy.

ErlNifTid - enif_thread_self(void) - - -

Same as erl_drv_thread_self. -

+ enif_thread_self(void) + + +

Same as + erl_drv_thread_self.

int enif_thread_type(void) - Determine type of current thread - -

Determine the type of currently executing thread. A positive value - indicates a scheduler thread while a negative value or zero indicates - another type of thread. Currently the following specific types exist - (which may be extended in the future):

- - ERL_NIF_THR_UNDEFINED -

Undefined thread that is not a scheduler thread.

- ERL_NIF_THR_NORMAL_SCHEDULER -

A normal scheduler thread.

- ERL_NIF_THR_DIRTY_CPU_SCHEDULER -

A dirty CPU scheduler thread.

- ERL_NIF_THR_DIRTY_IO_SCHEDULER -

A dirty I/O scheduler thread.

-
-
+ Determine type of current thread + +

Determine the type of currently executing thread. A positive value + indicates a scheduler thread while a negative value or zero indicates + another type of thread. Currently the following specific types exist + (which may be extended in the future):

+ + ERL_NIF_THR_UNDEFINED +

Undefined thread that is not a scheduler thread.

+ ERL_NIF_THR_NORMAL_SCHEDULER +

A normal scheduler thread.

+ ERL_NIF_THR_DIRTY_CPU_SCHEDULER +

A dirty CPU scheduler thread.

+ ERL_NIF_THR_DIRTY_IO_SCHEDULER +

A dirty I/O scheduler thread.

+
+
ErlNifTime - enif_time_offset(ErlNifTimeUnit time_unit) - Get current Time Offset - - -

Arguments:

- - time_unit - Time unit of returned value. - -

Returns the current time offset between - Erlang monotonic time - and - Erlang system time - converted into the time_unit passed as argument.

-

Returns ERL_NIF_TIME_ERROR if called with an invalid - time unit argument, or if called from a thread that is not a - scheduler thread.

-

See also: - ErlNifTime and - ErlNifTimeUnit. -

+ enif_time_offset(ErlNifTimeUnit time_unit) + Get current time offset. + + +

Returns the current time offset between + + Erlang monotonic time and + + Erlang system time + converted into the time_unit passed as argument.

+

time_unit is the time unit of the returned value.

+

Returns ERL_NIF_TIME_ERROR if called with an invalid + time unit argument or if called from a thread that is not a + scheduler thread.

+

See also ErlNifTime + and + ErlNifTimeUnit.

void * - enif_tsd_get(ErlNifTSDKey key) - - -

Same as erl_drv_tsd_get. -

+ enif_tsd_get(ErlNifTSDKey key) + + +

Same as + erl_drv_tsd_get.

int - enif_tsd_key_create(char *name, ErlNifTSDKey *key) - - -

Same as erl_drv_tsd_key_create. -

-
-
+ enif_tsd_key_create(char *name, ErlNifTSDKey *key) + + + +

Same as + erl_drv_tsd_key_create.

+
+
void - enif_tsd_key_destroy(ErlNifTSDKey key) - - -

Same as erl_drv_tsd_key_destroy. -

+ enif_tsd_key_destroy(ErlNifTSDKey key) + + +

Same as + erl_drv_tsd_key_destroy.

void - enif_tsd_set(ErlNifTSDKey key, void *data) - - -

Same as erl_drv_tsd_set. -

+ enif_tsd_set(ErlNifTSDKey key, void *data) + + +

Same as + erl_drv_tsd_set.

+
- SEE ALSO -

erlang:load_nif/2

+ See Also +

+ erlang:load_nif/2

diff --git a/erts/doc/src/erl_prim_loader.xml b/erts/doc/src/erl_prim_loader.xml index d3ece37cc5..86a3b98eda 100644 --- a/erts/doc/src/erl_prim_loader.xml +++ b/erts/doc/src/erl_prim_loader.xml @@ -30,95 +30,98 @@ erl_prim_loader.xml erl_prim_loader - Low Level Erlang Loader + Low-level Erlang loader. -

erl_prim_loader is used to load all Erlang modules into - the system. The start script is also fetched with this low level +

This module is used to load all Erlang modules into + the system. The start script is also fetched with this low-level loader.

+

erl_prim_loader knows about the environment and how to fetch modules.

-

The -loader Loader command line flag can be used to - choose the method used by the erl_prim_loader. Two + +

Command-line flag -loader Loader can be used to + choose the method used by erl_prim_loader. Two Loader methods are supported by the Erlang runtime system: efile and inet.

- -

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 - list_dir/1 and read_file_info/1 as well as the flag - -loader_debug are also experimental

-
- Get a file + Get a file. -

This function fetches a file using the low level loader. - Filename is either an absolute file name or just the name - of the file, for example "lists.beam". If an internal +

Fetches a file using the low-level loader. + Filename is either an absolute filename or only + the name of the file, for example, "lists.beam". If an internal path is set to the loader, this path is used to find the file. FullName is the complete name of the fetched file. Bin is the contents of the file as a binary.

- -

The Filename can also be a file in an archive. For example +

Filename can also be a file in an archive, + for example, $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia.beam. - See code(3) about archive files.

+ For information about archive files, see + kernel:code(3).

+ - Get the path set in the loader + Get the path set in the loader. -

This function gets the path set in the loader. The path is - set by the init process according to information found - in the start script.

+

Gets the path set in the loader. The path is + set by the init(3) + process according to information found in the start script.

+ - List files in a directory + List files in a directory.

Lists all the files in a directory. Returns - {ok, Filenames} if successful. Otherwise, it returns + {ok, Filenames} if successful, otherwise error. Filenames is a list of the names of all the files in the directory. The names are not sorted.

-

The Dir can also be a directory in an archive. For example +

Dir can also be a directory in an archive, + for example, $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin. - See code(3) about archive files.

+ For information about archive files, see + kernel:code(3).

+ - Get information about a file + Get information about a file.

Retrieves information about a file. Returns {ok, FileInfo} if successful, otherwise error. FileInfo is a record - file_info, defined in the Kernel include file + file_info, defined in the Kernel include file file.hrl. Include the following directive in the module from which the function is called:

-include_lib("kernel/include/file.hrl"). -

See file(3) for more info about - the record file_info.

-

The Filename can also be a file in an archive. For example +

For more information about the record file_info, see + kernel:file(3).

+

Filename can also be a file in an archive, + for example, $OTPROOT/lib/mnesia-4.4.7.ez/mnesia-4.4.7/ebin/mnesia. - See code(3) about archive files.

+ For information about archive files, see + kernel:code(3).

+ - Get information about a link or file + Get information about a link or file. -

This function works like - read_file_info/1 +

Works like + read_file_info/1 except that if Filename is a symbolic link, - information about the link will be returned in the file_info - record and the type field of the record will be set to + information about the link is returned in the file_info + record and the type field of the record is set to symlink.

If Filename is not a symbolic link, this function returns exactly the same result as read_file_info/1. @@ -126,20 +129,23 @@ is always equivalent to read_file_info/1.

+ - Set the path of the loader + Set the path of the loader. -

This function sets the path of the loader if init +

Sets the path of the loader if + init(3) interprets a path command in the start script.

- Command Line Flags + Command-Line Flags

The erl_prim_loader module interprets the following - command line flags:

+ command-line flags:

+ -loader Loader @@ -147,37 +153,38 @@ erl_prim_loader. Loader can be efile (use the local file system) or inet (load using the boot_server on another Erlang node).

-

If the -loader flag is omitted, it defaults to +

If flag -loader is omitted, it defaults to efile.

-loader_debug

Makes the efile loader write some debug information, - such as the reason for failures, while it handles files.

+ such as the reason for failures, while it handles files.

-hosts Hosts

Specifies which other Erlang nodes the inet loader - can use. This flag is mandatory if the -loader inet - flag is present. On each host, there must be on Erlang node - with the erl_boot_server(3) - which handles the load requests. - Hosts is a list of IP addresses (hostnames + can use. This flag is mandatory if flag -loader inet + is present. On each host, there must be on Erlang node + with the + kernel:erl_boot_server(3), + which handles the load requests. + Hosts is a list of IP addresses (hostnames are not acceptable).

-setcookie Cookie

Specifies the cookie of the Erlang runtime system. This flag - is mandatory if the -loader inet flag is present.

+ is mandatory if flag -loader inet is present.

- SEE ALSO -

init(3), - erl_boot_server(3)

+ See Also +

init(3), + + kernel:erl_boot_server(3)

diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index e2852ce49d..a2cfed684b 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -29,488 +29,618 @@ erl_tracer - Erlang Tracer Behaviour + Erlang tracer behavior. -

A behaviour module for implementing the back end of the erlang - tracing system. The functions in this module will be called whenever - a trace probe is triggered. Both the enabled and trace - functions are called in the context of the entity that triggered the - trace probe. - This means that the overhead by having the tracing enabled will be - greatly effected by how much time is spent in these functions. So do as - little work as possible in these functions.

+

This behavior module implements the back end of the Erlang + tracing system. The functions in this module are called whenever + a trace probe is triggered. Both the enabled and trace + functions are called in the context of the entity that triggered the + trace probe. + This means that the overhead by having the tracing enabled is + greatly effected by how much time is spent in these functions. So, do as + little work as possible in these functions.

+ -

All functions in this behaviour have to be implemented as NIF's. - This is a limitation that may the lifted in the future. - There is an example tracer module nif - implementation at the end of this page.

+

All functions in this behavior must be implemented as NIFs. + This limitation can be removed in a future releases. + An example tracer module NIF + implementation is provided at the end of this page.

+

Do not send messages or issue port commands to the Tracee - in any of the callbacks. Doing so is not allowed and can cause all - sorts of strange behaviour, including but not limited to infinite - recursions.

+ in any of the callbacks. This is not allowed and can cause all + sorts of strange behavior, including, but not limited to, infinite + recursions.

- - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + -

The different trace tags that the tracer will be called with. - Each trace tag is described in greater detail in - Module:trace/5 -

+

The different trace tags that the tracer is called with. + Each trace tag is described in detail in + Module:trace/5.

- + -

The process or port that the trace belongs to. -

+

The process or port that the trace belongs to.

- + -

The options for the tracee.

+

The options for the tracee:

timestamp - If set the tracer has been requested to include a timestamp. + If set the tracer has been requested to include a + time stamp. extra If set the tracepoint has included additonal data about - the trace event. What the additional data is depends on which - TraceTag has been triggered. The extra trace data - corresponds to the fifth elemnt in the trace tuples described in - erlang:trace/3. + the trace event. What the additional data is depends on which + TraceTag has been triggered. The extra trace data + corresponds to the fifth element in the trace tuples described in + + erlang:trace/3. match_spec_result If set the tracer has been requested to include the output - of a match specification that was run. + of a match specification that was run. scheduler_id - Set the scheduler id is to be included by the tracer. + If set the scheduler id is to be included by the tracer.
- + -

- The state which is given when calling - erlang:trace(PidPortSpec,true,[{tracer,Module,TracerState}]). - The tracer state is an immutable value that is passed to erl_tracer callbacks and should - contain all the data that is needed to generate the trace event. -

+

The state specified when calling + + erlang:trace(PidPortSpec,true,[{tracer,Module,TracerState}]). + The tracer state is an immutable value that is passed to + erl_tracer callbacks and is to + contain all the data that is needed to generate the trace event.

- CALLBACK FUNCTIONS -

The following functions - should be exported from a erl_tracer callback module.

- - Module:enabled/3 - Mandatory - Module:trace/5 - Mandatory - Module:enabled_procs/3 - Optional - Module:trace_procs/5 - Optional - Module:enabled_ports/3 - Optional - Module:trace_ports/5 - Optional - Module:enabled_running_ports/3 - Optional - Module:trace_running_ports/5 - Optional - Module:enabled_running_procs/3 - Optional - Module:trace_running_procs/5 - Optional + Callback Functions +

The following functions are to be exported from an erl_tracer + callback module:

+ + + + Module:enabled/3 + Mandatory + + Module:trace/5 + Mandatory + + Module:enabled_call/3 + Optional + + Module:trace_call/5 + Optional + + Module:enabled_garbage_collection/3 + Optional + + Module:trace_garbage_collection/5 + Optional + + Module:enabled_ports/3 + Optional + + Module:trace_ports/5 + Optional + + Module:enabled_procs/3 + Optional + + Module:trace_procs/5 + Optional + + Module:enabled_receive/3 + Optional + + Module:trace_receive/5 + Optional + + Module:enabled_running_ports/3 + Optional + + Module:trace_running_ports/5 + Optional + + Module:enabled_running_procs/3 + Optional + + Module:trace_running_procs/5 + Optional + + Module:enabled_send/3 + Optional + + Module:trace_send/5 + Optional -
Module:enabled(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. + Check if a trace event is to be generated. - TraceTag = trace_tag() | trace_status + TraceTag = + trace_tag() | trace_status TracerState = term() Tracee = tracee() - Result = trace | discard | remove + Result = trace | discard | remove -

This callback will be called whenever a tracepoint is triggered. It - allows the tracer to decide whether a trace should be generated or not. - This check is made as early as possible in order to limit the amount of - overhead associated with tracing. If trace is returned the - necessary trace data will be created and the trace call-back of the tracer - will be called. If discard is returned, this trace call - will be discarded and no call to trace will be done. -

-

trace_status is a special type of TraceTag which is used - to check if the tracer should still be active. It is called in multiple - scenarios, but most significantly it is used when tracing is started - using this tracer. If remove is returned when the trace_status - is checked, the tracer will be removed from the tracee.

-

This function may be called multiple times per tracepoint, so it - is important that it is both fast and side effect free.

+

This callback is called whenever a tracepoint is triggered. It + allows the tracer to decide whether a trace is to be generated or not. + This check is made as early as possible to limit the amount of + overhead associated with tracing. If trace is returned, the + necessary trace data is created and the trace callback of the tracer + is called. If discard is returned, this trace call is + discarded and no call to trace is done.

+

trace_status is a special type of TraceTag, which is + used to check if the tracer is still to be active. It is called in + multiple scenarios, but most significantly it is used when tracing + is started using this tracer. If remove is returned when the + trace_status is checked, the tracer is removed from the + tracee.

+

This function can be called multiple times per tracepoint, so it + is important that it is both fast and without side effects.

- Module:enabled_call(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_call() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - call | return_to - is triggered.

-

If enabled_call/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_call(TraceTag, TracerState, Tracee) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_call() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + call | return_to + is triggered.

+

If enabled_call/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_gc() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - garbage_collection - is triggered.

-

If enabled_garbage_collection/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_garbage_collection() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + garbage_collection + is triggered.

+

If enabled_garbage_collection/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_ports() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - ports - is triggered.

-

If enabled_ports/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_ports() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + ports + is triggered.

+

If enabled_ports/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_procs() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - procs - is triggered.

-

If enabled_procs/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_procs() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + procs + is triggered.

+

If enabled_procs/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_receive() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - 'receive' - is triggered.

-

If enabled_receive/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result + + Check if a trace event is to be generated. + + TraceTag = + trace_tag_receive() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + 'receive' + is triggered.

+

If enabled_receive/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_running_ports() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - running_ports - is triggered.

-

If enabled_running_ports/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> + Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_running_ports() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + running_ports + is triggered.

+

If enabled_running_ports/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_running_procs() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - running_procs | running - is triggered.

-

If enabled_running_procs/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> + Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_running_procs() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + + running_procs | running + is triggered.

+

If enabled_running_procs/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:enabled_send(TraceTag, TracerState, Tracee) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_send() - TracerState = term() - Tracee = tracee() - Result = trace | discard | remove - - -

This callback will be called whenever a tracepoint with trace flag - send - is triggered.

-

If enabled_send/3 is not defined enabled/3 will be called instead.

-
+ Module:enabled_send(TraceTag, TracerState, Tracee) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_send() + TracerState = term() + Tracee = tracee() + Result = trace | discard | remove + + +

This callback is called whenever a tracepoint with trace flag + send + is triggered.

+

If enabled_send/3 is undefined, + Module:enabled/3 + is called instead.

+
- Module:trace(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. + Module:trace(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. - TraceTag = trace_tag() + TraceTag = + trace_tag() TracerState = term() Tracee = tracee() - FirstTraceTerm = term() + TraceTerm = term() Opts = trace_opts() - Result = ok + Result = ok -

This callback will be called when a tracepoint is triggered and - the Module:enabled/3 - callback returned trace. In it any side effects needed by - the tracer should be done. The tracepoint payload is located in - the TraceTerm. The content of the TraceTerm depends on which - TraceTag has been triggered. - The TraceTerm corresponds to the - fourth element in the trace tuples described in - erlang:trace/3. - If the trace tuple has five elements, the fifth element will be sent as - the extra value in the Opts maps.

+

This callback is called when a tracepoint is triggered and the + Module:enabled/3 + callback returned trace. In it any side effects needed by + the tracer are to be done. The tracepoint payload is located in + the TraceTerm. The content of the TraceTerm + depends on which TraceTag is triggered. + TraceTerm corresponds to the + fourth element in the trace tuples described in + + erlang:trace/3.

+

If the trace tuple has five elements, the fifth element + will be sent as the extra value in the Opts maps.

+ - Module:trace(seq_trace, TracerState, Label, SeqTraceInfo, Opts) -> Result - Check if a sequence trace event should be generated. + Module:trace(seq_trace, TracerState, Label, + SeqTraceInfo, Opts) -> Result + Check if a sequence trace event is to be generated. TracerState = term() Label = term() SeqTraceInfo = term() Opts = trace_opts() - Result = ok + Result = ok -

The TraceTag seq_trace is handled a little bit - differently. There is not Tracee for seq_trace, instead the - Label associated with the seq_trace event is given. - For more info on what Label and SeqTraceInfo can be - see the seq_trace manual.

+

The TraceTag seq_trace is handled slightly + differently. There is no Tracee for seq_trace, instead + the Label associated with the seq_trace event is + specified.

+

For more information on what Label and SeqTraceInfo + can be, see + kernel:seq_trace.

- Module:trace_call(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_call() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_call/3 - callback returned trace.

-

If trace_call/5 is not defined trace/5 will be called instead.

-
+ Module:trace_call(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_call() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_call/3 + callback returned trace.

+

If trace_call/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_garbage_collection(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_gc() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_garbage_collection/3 - callback returned trace.

-

If trace_garbage_collection/5 is not defined trace/5 will be called instead.

-
+ Module:trace_garbage_collection(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_gc() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_garbage_collection/3 + callback returned trace.

+

If trace_garbage_collection/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_ports/3 - callback returned trace.

-

If trace_ports/5 is not defined trace/5 will be called instead.

-
+ Module:trace_ports(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_ports/3 + callback returned trace.

+

If trace_ports/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_procs/3 - callback returned trace.

-

If trace_procs/5 is not defined trace/5 will be called instead.

-
+ Module:trace_procs(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_procs/3 + callback returned trace.

+

If trace_procs/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_receive(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_receive() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_receive/3 - callback returned trace.

-

If trace_receive/5 is not defined trace/5 will be called instead.

-
+ Module:trace_receive(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_receive() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_receive/3 + callback returned trace.

+

If trace_receive/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_running_ports(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_running_ports() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_running_ports/3 - callback returned trace.

-

If trace_running_ports/5 is not defined trace/5 will be called instead.

-
+ Module:trace_running_ports(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_running_ports() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_running_ports/3 + callback returned trace.

+

If trace_running_ports/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_running_procs(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_running_procs() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_running_procs/3 - callback returned trace.

-

If trace_running_procs/5 is not defined trace/5 will be called instead.

-
+ Module:trace_running_procs(TraceTag, TracerState, Tracee, + TraceTerm, Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_running_procs() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_running_procs/3 + callback returned trace.

+

If trace_running_procs/5 is undefined, + Module:trace/5 + is called instead.

+
- Module:trace_send(TraceTag, TracerState, Tracee, TraceTerm, Opts) -> Result - Check if a trace event should be generated. - - TraceTag = trace_tag_send() - TracerState = term() - Tracee = tracee() - FirstTraceTerm = term() - Opts = trace_opts() - Result = ok - - -

This callback will be called when a tracepoint is triggered and - the Module:enabled_send/3 - callback returned trace.

-

If trace_send/5 is not defined trace/5 will be called instead.

-
+ Module:trace_send(TraceTag, TracerState, Tracee, TraceTerm, + Opts) -> Result + Check if a trace event is to be generated. + + TraceTag = + trace_tag_send() + TracerState = term() + Tracee = tracee() + TraceTerm = term() + Opts = trace_opts() + Result = ok + + +

This callback is called when a tracepoint is triggered and the + + Module:enabled_send/3 + callback returned trace.

+

If trace_send/5 is undefined, + Module:trace/5 + is called instead.

+
-
+
- Erl Tracer Module example -

In the example below a tracer module with a nif backend sends a message - for each send trace tag containing only the sender and receiver. - Using this tracer module, a much more lightweight message tracer is - used that only records who sent messages to who.

-

Here is an example session using it on Linux.

+ Erl Tracer Module Example +

In this example, a tracer module with a NIF back end sends a + message for each send trace tag containing only the sender and + receiver. Using this tracer module, a much more lightweight message + tracer is used, which only records who sent messages to who.

+ +

The following is an example session using it on Linux:

+
 $ gcc -I erts-8.0/include/ -fPIC -shared -o erl_msg_tracer.so erl_msg_tracer.c
 $ erl
@@ -533,9 +663,10 @@ ok
 {trace,#Port<0.490>,<0.4.0>}
 {ok,<0.40.0>}
 {trace,<0.41.0>,<0.27.0>}
-5>
-    
-

erl_msg_tracer.erl

+5> + +

erl_msg_tracer.erl:

+
 -module(erl_msg_tracer).
 
@@ -547,10 +678,11 @@ load() ->
 enabled(_, _, _) ->
     error.
 
-trace(_, _, _,_, _) ->
-    error.
-    
-

erl_msg_tracer.c

+trace(_, _, _, _, _) -> + error. + +

erl_msg_tracer.c:

+
 #include "erl_nif.h"
 
@@ -641,7 +773,6 @@ static ERL_NIF_TERM trace(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[])
     }
 
     return enif_make_atom(env, "ok");
-}
-    
+}
diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index cab18ac8b8..3356447168 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -32,18 +32,21 @@ erlang The Erlang BIFs. -

By convention, most Built-In Functions (BIFs) are seen as being +

By convention, most Built-In Functions (BIFs) are included in this module. Some of the BIFs are viewed more or less as part of the Erlang programming language and are auto-imported. Thus, it is not necessary to specify the module name. For example, the calls atom_to_list(Erlang) and erlang:atom_to_list(Erlang) are identical.

+

Auto-imported BIFs are listed without module prefix. BIFs listed with module prefix are not auto-imported.

+

BIFs can fail for various reasons. All BIFs fail with reason badarg if they are called with arguments of an incorrect type. The other reasons are described in the description of each individual BIF.

+

Some BIFs can be used in guard tests and are marked with "Allowed in guard tests".

@@ -53,107 +56,104 @@ ext_binary()

A binary data object, structured according to - the Erlang external term format.

+ the Erlang external term format.

- -

See erlang:process_flag(message_queue_data, MQD).

+ +

See + process_flag(message_queue_data, MQD).

- -

See erlang:timestamp/0.

+ +

See + erlang:timestamp/0.

-

- Supported time unit representations:

+ + +

Supported time unit representations:

- PartsPerSecond :: integer() >= 1 - + PartsPerSecond :: integer() >= 1 +

Time unit expressed in parts per second. That is, - the time unit equals 1/PartsPerSecond second.

- - seconds - + the time unit equals 1/PartsPerSecond second.

+
+ seconds +

Symbolic representation of the time unit - represented by the integer 1.

- - milli_seconds - + represented by the integer 1.

+
+ milli_seconds +

Symbolic representation of the time unit - represented by the integer 1000.

- - micro_seconds - + represented by the integer 1000.

+
+ micro_seconds +

Symbolic representation of the time unit - represented by the integer 1000000.

- - nano_seconds - + represented by the integer 1000000.

+
+ nano_seconds +

Symbolic representation of the time unit - represented by the integer 1000000000.

- - native - + represented by the integer 1000000000.

+
+ native +

Symbolic representation of the native time unit - used by the Erlang runtime system.

- -

The native time unit is determined at - runtime system start, and remains the same until - the runtime system terminates. If a runtime system - is stopped and then started again (even on the same - machine), the native time unit of the new - runtime system instance can differ from the - native time unit of the old runtime system - instance.

- -

One can get an approximation of the native - time unit by calling erlang:convert_time_unit(1, - seconds, native). The result equals the number - of whole native time units per second. In case - the number of native time units per second does - not add up to a whole number, the result is rounded downwards.

- - -

The value of the native time unit gives - you more or less no information at all about the - quality of time values. It sets a limit for - the - resolution - as well as for the - precision - of time values, - but it gives absolutely no information at all about the - accuracy - of time values. The resolution of the native time - unit and the resolution of time values can differ - significantly.

-
-
- - perf_counter - + used by the Erlang runtime system.

+

The native time unit is determined at + runtime system start, and remains the same until + the runtime system terminates. If a runtime system + is stopped and then started again (even on the same + machine), the native time unit of the new + runtime system instance can differ from the + native time unit of the old runtime system + instance.

+

One can get an approximation of the native + time unit by calling + + erlang:convert_time_unit(1, seconds, native). + The result equals the number + of whole native time units per second. If + the number of native time units per second does not + add up to a whole number, the result is rounded downwards.

+ +

The value of the native time unit gives + you more or less no information about the + quality of time values. It sets a limit for the + + resolution and for the + + precision of time values, + but it gives no information about the + + accuracy of time values. The resolution of + the native time unit and the resolution of time + values can differ significantly.

+
+
+ perf_counter +

Symbolic representation of the performance counter - time unit used by the Erlang runtime system.

- -

The perf_counter time unit behaves much in the same way - as the native time unit. That is it might differ inbetween - run-time restarts. You get values of this type by calling - os:perf_counter() -

+ time unit used by the Erlang runtime system.

+

The perf_counter time unit behaves much in the same way + as the native time unit. That is, it can differ between + runtime restarts. To get values of this type, call + + os:perf_counter().

- -
- -

The time_unit/0 type may be extended. Use - erlang:convert_time_unit/3 - in order to convert time values between time units.

- + +

The time_unit/0 type can be extended. + To convert time values between time units, use + + erlang:convert_time_unit/3.

@@ -182,61 +182,60 @@ - Computes adler32 checksum. + Compute adler32 checksum.

Computes and returns the adler32 checksum for - Data.

+ Data.

- Computes adler32 checksum. + Compute adler32 checksum.

Continues computing the adler32 checksum by combining - the previous checksum, OldAdler, with - the checksum of Data.

+ the previous checksum, OldAdler, with + the checksum of Data.

The following code:

- X = erlang:adler32(Data1), - Y = erlang:adler32(X,Data2). -

assigns the same value to Y as this:

+X = erlang:adler32(Data1), +Y = erlang:adler32(X,Data2). +

assigns the same value to Y as this:

- Y = erlang:adler32([Data1,Data2]). +Y = erlang:adler32([Data1,Data2]).
- Combines two adler32 checksums. + Combine two adler32 checksums.

Combines two previously computed adler32 checksums. - This computation requires the size of the data object for - the second checksum to be known.

+ This computation requires the size of the data object for + the second checksum to be known.

The following code:

- Y = erlang:adler32(Data1), - Z = erlang:adler32(Y,Data2). +Y = erlang:adler32(Data1), +Z = erlang:adler32(Y,Data2).

assigns the same value to Z as this:

- X = erlang:adler32(Data1), - Y = erlang:adler32(Data2), - Z = erlang:adler32_combine(X,Y,iolist_size(Data2)). +X = erlang:adler32(Data1), +Y = erlang:adler32(Data2), +Z = erlang:adler32_combine(X,Y,iolist_size(Data2)).
- Appends an extra element to a tuple. + Append an extra element to a tuple.

Returns a new tuple that has one element more than Tuple1, and contains the elements in - Tuple1 + Tuple1 followed by Term as the last element. - Semantically equivalent to + Semantically equivalent to list_to_tuple(tuple_to_list(Tuple1) ++ - [Term]), but much faster.

-

Example:

+ [Term]), but much faster. Example:

 > erlang:append_element({one, two}, three).
 {one,two,three}
@@ -245,32 +244,31 @@ - Applies a function to an argument list. + Apply a function to an argument list.

Calls a fun, passing the elements in Args - as arguments.

+ as arguments.

If the number of elements in the arguments are known at compile time, the call is better written as Fun(Arg1, Arg2, ... ArgN).

-

Earlier, Fun could also be given as +

Earlier, Fun could also be speciifed as {Module, Function}, equivalent to - apply(Module, Function, Args). This use is - deprecated and will stop working in a future release.

+ apply(Module, Function, Args). This use is + deprecated and will stop working in a future release.

- Applies a function to an argument list. + Apply a function to an argument list.

Returns the result of applying Function in Module to Args. - The applied function must + The applied function must be exported from Module. The arity of the function is - the length of Args.

-

Example:

+ the length of Args. Example:

 > apply(lists, reverse, [[a, b, c]]).
 [c,b,a]
@@ -278,39 +276,43 @@
 "Erlang"

If the number of arguments are known at compile time, the call is better written as - Module:Function(Arg1, Arg2, ..., ArgN).

-

Failure: error_handler:undefined_function/3 is called + Module:Function(Arg1, Arg2, ..., + ArgN).

+

Failure: + error_handler:undefined_function/3 is called if the applied function is not exported. The error handler can be redefined (see - process_flag/2). + process_flag/2). If error_handler is undefined, or if the user has redefined the default error_handler so the replacement - module is undefined, an error with the reason undef + module is undefined, an error with reason undef is generated.

- Returns the binary representation of an atom. + Return the binary representation of an atom.

Returns a binary corresponding to the text representation of Atom. If Encoding - is latin1, there is one byte for each character + is latin1, one byte exists for each character in the text representation. If Encoding is utf8 or unicode, the characters are encoded using UTF-8 (that is, characters from 128 through 255 are encoded in two bytes).

-

atom_to_binary(Atom, latin1) never - fails because the text representation of an atom can only - contain characters from 0 through 255. In a future release, - the text representation - of atoms can be allowed to contain any Unicode character and - atom_to_binary(Atom, latin1) will then fail if the - text representation for Atom contains a Unicode - character greater than 255.

+ +

atom_to_binary(Atom, latin1) never + fails, as the text representation of an atom can only + contain characters from 0 through 255. In a future release, + the text representation + of atoms can be allowed to contain any Unicode character and + atom_to_binary(Atom, latin1) then fails if the + text representation for Atom contains a Unicode + character > 255.

+

Example:

 > atom_to_binary('Erlang', latin1).
@@ -332,12 +334,12 @@
 
     
       
-      Extracts a part of a binary.
+      Extract a part of a binary.
       
       

Extracts the part of the binary described by PosLen.

Negative length can be used to extract bytes at the end - of a binary, for example:

+ of a binary, for example:

1> Bin = <<1,2,3,4,5,6,7,8,9,10>>. 2> binary_part(Bin,{byte_size(Bin), -5}). @@ -349,43 +351,44 @@ 1> Bin = <<1,2,3>> 2> binary_part(Bin,{0,2}). <<1,2>> -

For details about the PosLen semantics, see the - binary - manual page in STDLIB.

+

For details about the PosLen semantics, see + stdlib:binary.

Allowed in guard tests.

- Extracts a part of a binary. + Extract a part of a binary.

The same as binary_part(Subject, - {Start, Length}).

+ {Start, Length}).

Allowed in guard tests.

- Converts from text representation to an atom. + Convert from text representation to an atom.

Returns the atom whose text representation is - Binary. - If Encoding is latin1, no - translation of bytes in the binary is done. - If Encoding - is utf8 or unicode, the binary must contain - valid UTF-8 sequences. Only Unicode characters up - to 255 are allowed.

-

binary_to_atom(Binary, utf8) fails if - the binary contains Unicode characters greater than 255. - In a future release, such Unicode characters can be allowed - and binary_to_atom(Binary, utf8) does then not fail. - For more information on Unicode support in atoms, see the - note on UTF-8 - encoded atoms - in Section "External Term Format" in the User's Guide.

+ Binary. + If Encoding is latin1, no + translation of bytes in the binary is done. + If Encoding + is utf8 or unicode, the binary must contain + valid UTF-8 sequences. Only Unicode characters up + to 255 are allowed.

+ +

binary_to_atom(Binary, utf8) fails if + the binary contains Unicode characters > 255. + In a future release, such Unicode characters can be allowed and + binary_to_atom(Binary, utf8) does then not fail. + For more information about Unicode support in atoms, see the + note on UTF-8 + encoded atoms + in section "External Term Format" in the User's Guide.

+

Examples:

 > binary_to_atom(<<"Erlang">>, latin1).
@@ -399,10 +402,10 @@
 
     
       
-      Converts from text representation to an atom.
+      Convert from text representation to an atom.
       
         

As - binary_to_atom/2, + binary_to_atom/2, but the atom must exist.

Failure: badarg if the atom does not exist.

@@ -410,7 +413,7 @@ - Converts from text representation to a float. + Convert from text representation to a float.

Returns the float whose text representation is Binary, for example:

@@ -424,7 +427,7 @@ - Converts from text representation to an integer. + Convert from text representation to an integer.

Returns an integer whose text representation is Binary, for example:

@@ -438,10 +441,11 @@ - Converts from text representation to an integer. + Convert from text representation to an integer.

Returns an integer whose text representation in base - Base is Binary, for example:

+ Base is Binary, for + example:

 > binary_to_integer(<<"3FF">>, 16).
 1023
@@ -452,7 +456,7 @@ - Converts a binary to a list. + Convert a binary to a list.

Returns a list of integers corresponding to the bytes of Binary.

@@ -461,75 +465,83 @@ - Converts part of a binary to a list. - 1..byte_size(Binary) + Convert part of a binary to a list. + 1..byte_size(Binary) +

As binary_to_list/1, but returns a list of integers corresponding to the bytes from position Start to position Stop in Binary. - The positions in the + The positions in the binary are numbered starting from 1.

-

The one-based indexing for binaries used by - this function is deprecated. New code is to use - binary:bin_to_list/3 - in STDLIB instead. All functions in module - binary consistently use zero-based indexing.

+ +

The one-based indexing for binaries used by + this function is deprecated. New code is to use + + binary:bin_to_list/3 + in STDLIB instead. All functions in module + binary consistently use zero-based indexing.

+
- Decodes an Erlang external term format binary. + Decode an Erlang external term format binary.

Returns an Erlang term that is the result of decoding binary object Binary, which must be encoded according to the Erlang external term format.

-

When decoding binaries from untrusted sources, - consider using binary_to_term/2 to prevent Denial - of Service attacks.

+ +

When decoding binaries from untrusted sources, + consider using binary_to_term/2 to prevent Denial + of Service attacks.

+

See also - term_to_binary/1 - and - binary_to_term/2.

+ term_to_binary/1 + and + binary_to_term/2.

- Decodes an Erlang external term format binary. + Decode an Erlang external term format binary.

As binary_to_term/1, but takes options that affect decoding - of the binary.

+ of the binary.

+

Option:

safe

Use this option when receiving binaries from an untrusted - source.

+ source.

When enabled, it prevents decoding data that can be used to - attack the Erlang system. In the event of receiving unsafe - data, decoding fails with a badarg error.

+ attack the Erlang system. In the event of receiving unsafe + data, decoding fails with a badarg error.

This prevents creation of new atoms directly, - creation of new atoms indirectly (as they are embedded in - certain structures, such as process identifiers, - refs, and funs), and - creation of new external function references. - None of those resources are garbage collected, so unchecked - creation of them can exhaust available memory.

+ creation of new atoms indirectly (as they are embedded in + certain structures, such as process identifiers, + refs, and funs), and + creation of new external function references. + None of those resources are garbage collected, so unchecked + creation of them can exhaust available memory.

Failure: badarg if safe is specified and unsafe - data is decoded.

+ data is decoded.

See also - term_to_binary/1, - binary_to_term/1, - and - list_to_existing_atom/1.

+ term_to_binary/1, + + binary_to_term/1, and + + list_to_existing_atom/1.

- Returns the size of a bitstring. + Return the size of a bitstring.

Returns an integer that is the size in bits of Bitstring, for example:

@@ -544,7 +556,7 @@ - Converts a bitstring to a list. + Convert a bitstring to a list.

Returns a list of integers corresponding to the bytes of Bitstring. If the number of bits in the binary @@ -555,14 +567,14 @@ - Increments the reduction counter. + Increment the reduction counter.

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. A context switch is forced when the counter reaches the maximum number of - reductions for a process (2000 reductions in OTP R12B).

+ reductions for a process (2000 reductions in Erlang/OTP R12B).

This BIF can be removed in a future version of the Beam machine without prior warning. It is unlikely to be @@ -573,13 +585,12 @@ - Returns the size of a bitstring (or binary). + Return the size of a bitstring (or binary).

Returns an integer that is the number of bytes needed to contain Bitstring. That is, if the number of bits in Bitstring is not divisible by 8, the resulting - number of bytes is rounded up.

-

Examples:

+ number of bytes is rounded up. Examples:

 > byte_size(<<433:16,3:3>>).
 3
@@ -591,134 +602,126 @@
 
     
       
-      Cancels a timer.
+      Cancel a timer.
       
         

Cancels a timer. The same as calling - erlang:cancel_timer(TimerRef, - []).

+ + erlang:cancel_timer(TimerRef, []).

- Cancels a timer. - -

- Cancels a timer that has been created by - erlang:start_timer(), - or erlang:send_after(). - TimerRef identifies the timer, and - was returned by the BIF that created the timer. -

-

Available Options:

+ Cancel a timer. + +

Cancels a timer that has been created by + + erlang:start_timer or + erlang:send_after. + TimerRef identifies the timer, and + was returned by the BIF that created the timer.

+

Options:

{async, Async} -

- Asynchronous request for cancellation. Async - defaults to false which will cause the - cancellation to be performed synchronously. When - Async is set to true, the cancel - operation is performed asynchronously. That is, - erlang:cancel_timer() will send an asynchronous - request for cancellation to the timer service that - manages the timer, and then return ok. -

-
+

Asynchronous request for cancellation. Async + defaults to false, which causes the + cancellation to be performed synchronously. When + Async is set to true, the cancel + operation is performed asynchronously. That is, + cancel_timer() sends an asynchronous + request for cancellation to the timer service that + manages the timer, and then returns ok.

+ {info, Info} -

- Request information about the Result - of the cancellation. Info defaults to true - which means the Result is - given. When Info is set to false, no - information about the result of the cancellation - is given. When the operation is performed

- - synchronously - -

- If Info is true, the Result is - returned by erlang:cancel_timer(); otherwise, - ok is returned. -

-
- asynchronously - -

- If Info is true, a message on the form - {cancel_timer, TimerRef, - Result} is sent to the - caller of erlang:cancel_timer() when the - cancellation operation has been performed; otherwise, - no message is sent. -

-
-
-
-
-

- More Options may be added in the future. -

-

If Result is an integer, it represents - the time in milli-seconds left until the canceled timer would - have expired.

-

- If Result is false, a - timer corresponding to TimerRef could not - be found. This can be either because the timer had expired, - already had been canceled, or because TimerRef - never corresponded to a timer. Even if the timer had expired, - it does not tell you whether or not the timeout message has - arrived at its destination yet. -

- -

- The timer service that manages the timer may be co-located - with another scheduler than the scheduler that the calling - process is executing on. If this is the case, communication - with the timer service takes much longer time than if it - is located locally. If the calling process is in critical - path, and can do other things while waiting for the result - of this operation, or is not interested in the result of - the operation, you want to use option {async, true}. - If using option {async, false}, the calling - process blocks until the operation has been performed. -

-
-

See also +

Requests information about the Result + of the cancellation. Info defaults to true, + which means the Result is + given. When Info is set to false, no + information about the result of the cancellation + is given.

+ + +

When the operation is performed synchronously: + if Info is true, the Result is + returned by erlang:cancel_timer(). otherwise + ok is returned.

+
+ +

When the operation is performed asynchronously: + if Info is true, a message on the form + {cancel_timer, TimerRef, + Result} is sent to the + caller of erlang:cancel_timer() when the + cancellation operation has been performed, otherwise + no message is sent.

+
+
+ + +

More Options may be added in the future.

+

If Result is an integer, it represents + the time in milliseconds left until the canceled timer would + have expired.

+

If Result is false, a + timer corresponding to TimerRef could not + be found. This can be either because the timer had expired, + already had been canceled, or because TimerRef + never corresponded to a timer. Even if the timer had expired, + it does not tell you if the time-out message has + arrived at its destination yet.

+ +

The timer service that manages the timer can be co-located + with another scheduler than the scheduler that the calling + process is executing on. If so, communication + with the timer service takes much longer time than if it + is located locally. If the calling process is in critical + path, and can do other things while waiting for the result + of this operation, or is not interested in the result of + the operation, you want to use option {async, true}. + If using option {async, false}, the calling + process blocks until the operation has been performed.

+
+

See also erlang:send_after/4, - erlang:start_timer/4, - and - erlang:read_timer/2.

+ + erlang:start_timer/4, and + + erlang:read_timer/2.

+ - Checks if a module has old code. + Check if a module has old code.

Returns true if Module has old code, - otherwise false.

-

See also code(3).

+ otherwise false.

+

See also + kernel:code(3).

- Checks if a process executes old code for a module. + Check if a process executes old code for a module.

The same as - erlang:check_process_code(Pid, Module, []).

+ + check_process_code(Pid, Module, []) + .

- Checks if a process executes old code for a module. + Check if a process executes old code for a module. -

Checks if the node local process identified by Pid - executes old code for Module.

-

The available Options are as follows:

+

Checks if the node local process identified by + Pid + executes old code for Module.

+

Options:

{allow_gc, boolean()} @@ -726,30 +729,30 @@ the operation. If {allow_gc, false} is passed, and a garbage collection is needed to determine the result of the operation, the operation is aborted (see - information on CheckResult in the following). + information on CheckResult below). The default is to allow garbage collection, that is, {allow_gc, true}.

-
+ {async, RequestId}

The function check_process_code/3 returns the value async immediately after the request has been sent. When the request has been processed, the process that called this function is passed a - message on the form - {check_process_code, RequestId, CheckResult}.

-
+ message on the form {check_process_code, RequestId, + CheckResult}.

+

If Pid equals self(), and - no async option has been passed, the operation - is performed at once. Otherwise a request for - the operation is sent to the process identified by - Pid, and is handled when - appropriate. If no async option has been passed, - the caller blocks until CheckResult - is available and can be returned.

+ no async option has been passed, the operation + is performed at once. Otherwise a request for + the operation is sent to the process identified by + Pid, and is handled when + appropriate. If no async option has been passed, + the caller blocks until CheckResult + is available and can be returned.

CheckResult informs about the result of - the request as follows:

+ the request as follows:

true @@ -759,54 +762,59 @@ code for this module, or the process has references to old code for this module, or the process contains funs that references old code for this module.

-
+ false

The process identified by Pid does not execute old code for Module.

-
+ aborted

The operation was aborted, as the process needed to be garbage collected to determine the operation result, and the operation was requested - by passing option {allow_gc, false}.

+ by passing option {allow_gc, false}.

+
-

See also code(3).

+

See also + kernel:code(3).

Failures:

badarg - If Pid is not a node local process identifier. - + If Pid is not a node local process + identifier. + badarg If Module is not an atom. - + badarg If OptionList is an invalid list of options. - +
- Converts time unit of a time value. + Convert time unit of a time value. -

Converts the Time value of time unit - FromUnit to the corresponding - ConvertedTime value of time unit - ToUnit. The result is rounded - using the floor function.

- -

You may lose accuracy and precision when converting - between time units. In order to minimize such loss, collect all - data at native time unit and do the conversion on the end - result.

+

Converts the Time value of time unit + FromUnit to the corresponding + ConvertedTime value of time unit + ToUnit. The result is rounded + using the floor function.

+ +

You can lose accuracy and precision when converting + between time units. To minimize such loss, collect all + data at native time unit and do the conversion on the end + result.

+
+ - Computes crc32 (IEEE 802.3) checksum. + Compute crc32 (IEEE 802.3) checksum.

Computes and returns the crc32 (IEEE 802.3 style) checksum for Data.

@@ -815,37 +823,37 @@ - Computes crc32 (IEEE 802.3) checksum. + Compute crc32 (IEEE 802.3) checksum.

Continues computing the crc32 checksum by combining - the previous checksum, OldCrc, with the checksum of - Data.

+ the previous checksum, OldCrc, with the checksum + of Data.

The following code:

- X = erlang:crc32(Data1), - Y = erlang:crc32(X,Data2). +X = erlang:crc32(Data1), +Y = erlang:crc32(X,Data2).

assigns the same value to Y as this:

- Y = erlang:crc32([Data1,Data2]). +Y = erlang:crc32([Data1,Data2]).
- Combines two crc32 (IEEE 802.3) checksums. + Combine two crc32 (IEEE 802.3) checksums.

Combines two previously computed crc32 checksums. - This computation requires the size of the data object for - the second checksum to be known.

+ This computation requires the size of the data object for + the second checksum to be known.

The following code:

- Y = erlang:crc32(Data1), - Z = erlang:crc32(Y,Data2). +Y = erlang:crc32(Data1), +Z = erlang:crc32(Y,Data2).

assigns the same value to Z as this:

- X = erlang:crc32(Data1), - Y = erlang:crc32(Data2), - Z = erlang:crc32_combine(X,Y,iolist_size(Data2)). +X = erlang:crc32(Data1), +Y = erlang:crc32(Data2), +Z = erlang:crc32_combine(X,Y,iolist_size(Data2)).
@@ -855,8 +863,7 @@

Returns the current date as {Year, Month, Day}.

The time zone and Daylight Saving Time correction depend on - the underlying OS.

-

Example:

+ the underlying OS. Example:

 > date().
 {1995,2,19}
@@ -865,28 +872,29 @@ - Extracts a protocol packet from a binary. + Extract a protocol packet from a binary.

Decodes the binary Bin according to the packet - protocol specified by Type. Similar to the packet - handling done by sockets with option {packet,Type}.

+ protocol specified by Type. Similar to the packet + handling done by sockets with option + {packet,Type}.

If an entire packet is contained in Bin, it is - returned together with the remainder of the binary as - {ok,Packet,Rest}.

+ returned together with the remainder of the binary as + {ok,Packet,Rest}.

If Bin does not contain the entire packet, - {more,Length} is returned. - Length is either the - expected total size of the packet, or undefined - if the expected packet size is unknown. decode_packet - can then be called again with more data added.

+ {more,Length} is returned. + Length is either the + expected total size of the packet, or undefined + if the expected packet size is unknown. decode_packet + can then be called again with more data added.

If the packet does not conform to the protocol format, - {error,Reason} is returned.

-

The following Types are valid:

+ {error,Reason} is returned.

+

Types:

raw | 0

No packet handling is done. The entire binary is - returned unless it is empty.

+ returned unless it is empty.

1 | 2 | 4 @@ -898,10 +906,10 @@ line -

A packet is a line terminated by a delimiter byte, - default is the latin1 newline character. The delimiter - byte is included in the returned packet unless the line - was truncated according to option line_length.

+

A packet is a line-terminated by a delimiter byte, + default is the latin-1 newline character. The delimiter + byte is included in the returned packet unless the line + was truncated according to option line_length.

asn1 | cdr | sunrm | fcgi | tpkt @@ -918,53 +926,51 @@ http | httph | http_bin | httph_bin

The Hypertext Transfer Protocol. The packets - are returned with the format according to - HttpPacket described earlier. - A packet is either a - request, a response, a header, or an end of header - mark. Invalid lines are returned as - HttpError.

+ are returned with the format according to + HttpPacket described earlier. + A packet is either a + request, a response, a header, or an end of header + mark. Invalid lines are returned as + HttpError.

Recognized request methods and header fields are returned - as atoms. Others are returned as strings. Strings of - unrecognized header fields are formatted with only - capital letters first and after hyphen characters, for - example, "Sec-Websocket-Key".

+ as atoms. Others are returned as strings. Strings of + unrecognized header fields are formatted with only + capital letters first and after hyphen characters, for + example, "Sec-Websocket-Key".

The protocol type http is only to be used for - the first line when an HttpRequest or an - HttpResponse is expected. - The following calls are to use httph to get - HttpHeaders until - http_eoh is returned, which marks the end of the - headers and the beginning of any following message body.

+ the first line when an HttpRequest or an + HttpResponse is expected. + The following calls are to use httph to get + HttpHeaders until + http_eoh is returned, which marks the end of the + headers and the beginning of any following message body.

The variants http_bin and httph_bin return - strings (HttpString) as binaries instead of lists.

+ strings (HttpString) as binaries instead of lists.

-

The following options are available:

- - {packet_size, integer() >= 0} - -

Sets the maximum allowed size of the packet body. - If the packet header indicates that the length of the - packet is longer than the maximum allowed length, the - packet is considered invalid. Default is 0, which means - no size limit.

-
- {line_length, integer() >= 0} - +

Options:

+ + {packet_size, integer() >= 0} +

Sets the maximum allowed size of the packet body. + If the packet header indicates that the length of the + packet is longer than the maximum allowed length, the + packet is considered invalid. Defaults to 0, which means + no size limit.

+
+ {line_length, integer() >= 0} +

For packet type line, lines longer than the indicated length are truncated.

-

Option line_length also applies to http* - packet types as an alias for option packet_size - if packet_size itself is not set. This use is - only intended for backward compatibility.

-
- {line_delimiter, 0 =< byte() =< 255} - -

For packet type line, sets the delimiting byte. - Default is the latin1 character $\n.

-
-
+

Option line_length also applies to http* + packet types as an alias for option packet_size + if packet_size itself is not set. This use is + only intended for backward compatibility.

+
+ {line_delimiter, 0 =< byte() =< 255} +

For packet type line, sets the delimiting byte. + Default is the latin-1 character $\n.

+
+

Examples:

 > erlang:decode_packet(1,<<3,"abcd">>,[]).
@@ -976,7 +982,7 @@
 
     
       
-      Deletes element at index in a tuple.
+      Delete element at index in a tuple.
       1..tuple_size(Tuple1)
       
         

Returns a new tuple with element at Index @@ -989,16 +995,16 @@ - Makes the current code for a module old. + Make the current code for a module old. -

Makes the current code for Module become old code, - and deletes all references for this module from the export table. +

Makes the current code for Module become old + code and deletes all references for this module from the export table. Returns undefined if the module does not exist, otherwise true.

This BIF is intended for the code server (see - code(3)) and is not - to be used elsewhere.

+ kernel:code(3)) + and is not to be used elsewhere.

Failure: badarg if there already is an old version of Module.

@@ -1007,54 +1013,56 @@ - Stops monitoring. + Stop monitoring.

If MonitorRef is a reference that the calling process obtained by calling - monitor/2, + monitor/2, this monitoring is turned off. If the monitoring is already turned off, nothing happens.

Once demonitor(MonitorRef) has returned, it is guaranteed that no {'DOWN', MonitorRef, _, _, _} message, because of the monitor, will be placed in the caller message queue - in the future. A {'DOWN', + in the future. However, a {'DOWN', MonitorRef, _, _, _} message can have been placed in the caller message queue before - the call, though. It is therefore usually advisable + the call. It is therefore usually advisable to remove such a 'DOWN' message from the message queue after monitoring has been stopped. - demonitor(MonitorRef, [flush]) - can be used instead of - demonitor(MonitorRef) if this cleanup is wanted.

+ + demonitor(MonitorRef, [flush]) + can be used instead of demonitor(MonitorRef) + if this cleanup is wanted.

-

Prior to OTP release R11B (ERTS version 5.5) demonitor/1 - behaved completely asynchronously, i.e., the monitor was active +

Before Erlang/OTP R11B (ERTS 5.5) demonitor/1 + behaved completely asynchronously, that is, the monitor was active until the "demonitor signal" reached the monitored entity. This had one undesirable effect. You could never know when you were guaranteed not to receive a DOWN message - due to the monitor.

-

Current behavior can be viewed as two combined operations: + because of the monitor.

+

The current behavior can be viewed as two combined operations: asynchronously send a "demonitor signal" to the monitored entity - and ignore any future results of the monitor.

+ and ignore any future results of the monitor.

Failure: It is an error if MonitorRef refers to a monitoring started by another process. Not all such cases are cheap to check. If checking is cheap, the call fails with - badarg for example, if MonitorRef is a + badarg, for example if MonitorRef is a remote reference.

- Stops monitoring. + Stop monitoring.

The returned value is true unless info is part of OptionList.

demonitor(MonitorRef, []) is equivalent to - demonitor(MonitorRef).

-

The available Options are as follows:

+ + demonitor(MonitorRef).

+

Options:

flush @@ -1065,28 +1073,28 @@

Calling demonitor(MonitorRef, [flush]) is equivalent to the following, but more efficient:

- demonitor(MonitorRef), - receive - {_, MonitorRef, _, _, _} -> - true - after 0 -> - true - end +demonitor(MonitorRef), +receive + {_, MonitorRef, _, _, _} -> + true +after 0 -> + true +end
info

The returned value is one of the following:

true - The monitor was found and removed. In this case, +

The monitor was found and removed. In this case, no 'DOWN' message corresponding to this - monitor has been delivered and will not be delivered. + monitor has been delivered and will not be delivered.

false - The monitor was not found and could not be removed. +

The monitor was not found and could not be removed. This probably because someone already has placed a 'DOWN' message corresponding to this monitor - in the caller message queue. + in the caller message queue.

If option info is combined with option flush, @@ -1101,21 +1109,21 @@ badarg If OptionList is not a list. - + badarg If Option is an invalid option. - + badarg The same failure as for - demonitor/1. - + demonitor/1. + - Forces the disconnection of a node. + Force the disconnection of a node.

Forces the disconnection of a node. This appears to the node Node as if the local node has crashed. @@ -1129,7 +1137,7 @@ - Prints a term on standard output. + Print a term on standard output.

Prints a text representation of Term on the standard output.

@@ -1141,7 +1149,7 @@ - Returns the Nth element of a tuple. + Return the Nth element of a tuple. 1..tuple_size(Tuple)

Returns the Nth element (numbering from 1) of @@ -1155,7 +1163,7 @@ b

- Returns and deletes the process dictionary. + Return and delete the process dictionary.

Returns the process dictionary and deletes it, for example:

@@ -1169,13 +1177,13 @@ b
- Returns and deletes a value from the process dictionary. + Return and delete a value from the process dictionary. +

Returns the value Val associated with Key and deletes it from the process dictionary. Returns undefined if no value is associated with - Key.

-

Example:

+ Key. Example:

 > put(key1, {merry, lambs, are, playing}),
 X = erase(key1),
@@ -1186,16 +1194,15 @@ b
- Stops execution with a given reason. + Stop execution with a specified reason.

Stops the execution of the calling process with the reason Reason, where Reason is any term. The exit reason is {Reason, Where}, where Where 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.

-

Example:

+ function first). As evaluating this function causes + the process to terminate, it has no return value. Example:

 > catch error(foobar).
 {'EXIT',{foobar,[{erl_eval,do_apply,5},
@@ -1208,7 +1215,7 @@ b
- Stops execution with a given reason. + Stop execution with a specified reason.

Stops the execution of the calling process with the reason Reason, where Reason @@ -1218,21 +1225,20 @@ b

function first). Args is expected to be the list of arguments for the current function; in Beam it is used to provide the arguments for the current function in - the term Where. Since evaluating this function causes + the term Where. As evaluating this function causes the process to terminate, it has no return value.

- Stops execution with a given reason. + Stop execution with a specified reason.

Stops the execution of the calling process with exit reason Reason, where Reason - is any term. Since + is any term. As evaluating this function causes the process to terminate, it - has no return value.

-

Example:

+ has no return value. Example:

 > exit(foobar).
 ** exception exit: foobar
@@ -1243,44 +1249,44 @@ b
- Sends an exit signal to a process or a port. + Send an exit signal to a process or a port.

Sends an exit signal with exit reason Reason to the process or port identified by Pid.

The following behavior applies if Reason is any term, except normal or kill:

- - - If Pid is not trapping exits, - Pid - itself exits with exit reason Reason. - - If Pid is trapping exits, the exit - signal is transformed into a message - {'EXIT', From, Reason} - and delivered to the message queue of Pid. - - From is the process identifier of the process - that sent the exit signal. See also - process_flag/2. - - -

If Reason is the atom normal, + +

If Pid is not trapping exits, Pid - does not exit. If it is trapping exits, the exit signal is - transformed into a message {'EXIT', From, normal} - and delivered to its message queue.

-

If Reason is the atom kill, - that is, if exit(Pid, kill) is called, - an untrappable exit signal is sent to Pid, - which unconditionally exits with exit reason killed. -

+ itself exits with exit reason Reason.

+ +

If Pid is trapping exits, the exit + signal is transformed into a message + {'EXIT', From, Reason} + and delivered to the message queue of Pid.

+
+

From is the process identifier of the process + that sent the exit signal. See also + + process_flag/2.

+
+ +

If Reason is the atom normal, + Pid + does not exit. If it is trapping exits, the exit signal is + transformed into a message {'EXIT', From, normal} + and delivered to its message queue.

+

If Reason is the atom kill, + that is, if exit(Pid, kill) is called, + an untrappable exit signal is sent to Pid, + which unconditionally exits with exit reason killed.

- Calculates the maximum size for a term encoded in the Erlang external term format. + Calculate the maximum size for a term encoded in the Erlang + external term format.

Calculates, without doing the encoding, the maximum byte size for a term encoded in the Erlang external term format. The following @@ -1291,13 +1297,15 @@ b

> true = Size1 =< Size2. true

This is equivalent to a call to:

-erlang:external_size(Term, []) + +erlang:external_size(Term, [])
- Calculates the maximum size for a term encoded in the Erlang external term format. + Calculate the maximum size for a term encoded in the Erlang + external term format.

Calculates, without doing the encoding, the maximum byte size for a term encoded in the Erlang external term format. The following @@ -1309,13 +1317,14 @@ true true

Option {minor_version, Version} specifies how floats are encoded. For a detailed description, see - term_to_binary/2.

+ + term_to_binary/2.

- Converts a number to a float. + Convert a number to a float.

Returns a float by converting Number to a float, for example:

@@ -1326,7 +1335,8 @@ true

If used on the top level in a guard, it tests whether the argument is a floating point number; for clarity, use - is_float/1 instead.

+ is_float/1 + instead.

When float/1 is used in an expression in a guard, such as 'float(A) == 4.0', it converts a number as described earlier.

@@ -1345,13 +1355,14 @@ true - Text representation of a float formatted using given options. + Text representation of a float formatted using specified + options.

Returns a binary corresponding to the text representation of Float using fixed decimal point formatting. Options behaves in the same - way as float_to_list/2.

-

Examples:

+ way as + float_to_list/2. Examples:

 > float_to_binary(7.12, [{decimals, 4}]).
 <<"7.1200">>
@@ -1371,27 +1382,29 @@ true
- Text representation of a float formatted using given options. + Text representation of a float formatted using specified + options.

Returns a string corresponding to the text representation - of Float using fixed decimal point formatting. The - options are as follows:

+ of Float using fixed decimal point formatting.

+

Available options:

- If option decimals is specified, the returned value +

If option decimals is specified, the returned value contains at most Decimals number of digits past the - decimal point. If the number does not fit in the internal - static buffer of 256 bytes, the function throws badarg. + decimal point. If the number does not fit in the internal + static buffer of 256 bytes, the function throws badarg.

- If option compact is provided, the trailing zeros +

If option compact is specified, the trailing zeros at the end of the list are truncated. This option is only - meaningful together with option decimals. + meaningful together with option decimals.

- If option scientific is provided, the float is +

If option scientific is specified, the float is formatted using scientific notation with Decimals - digits of precision. + digits of precision.

- If Options is [], the function behaves as - float_to_list/1. +

If Options is [], the function behaves as + + float_to_list/1.

Examples:

@@ -1418,16 +1431,16 @@ true

Two types of funs have slightly different semantics:

- A fun created by fun M:F/A is called an +

A fun created by fun M:F/A is called an external fun. Calling it will always call the function F with arity A in the latest code for module M. Notice that module M does not even - need to be loaded when the fun fun M:F/A is created. + need to be loaded when the fun fun M:F/A is created.

- All other funs are called local. When a local fun +

All other funs are called local. When a local fun is called, the same version of the code that created the fun is called (even if a newer version of the module has been - loaded). + loaded).

The following elements are always present in the list @@ -1491,14 +1504,14 @@ true {new_uniq, Uniq}

Uniq (a binary) is a unique value for this fun. It - is calculated from the compiled code for the entire module.

+ is calculated from the compiled code for the entire module.

{uniq, Uniq}

Uniq (an integer) is a unique value for this fun. - As from OTP R15, this integer is calculated from the - compiled code for the entire module. Before OTP R15, this - integer was based on only the body of the fun.

+ As from Erlang/OTP R15, this integer is calculated from the + compiled code for the entire module. Before Erlang/OTP R15, this + integer was based on only the body of the fun.

@@ -1520,7 +1533,7 @@ true uniq, and pid. For an external fun, the value of any of these items is always the atom undefined.

See - erlang:fun_info/1.

+ erlang:fun_info/1.

@@ -1535,20 +1548,24 @@ true - Checks if a function is exported and loaded. + Check if a function is exported and loaded. -

Returns true if the module Module is loaded - and contains an exported function Function/Arity, - or if there is a BIF (a built-in function implemented in C) - with the given name, otherwise returns false.

-

This function used to return false for built-in - functions before the 18.0 release.

+

Returns true if the module Module is + loaded and contains an exported function + Function/Arity, + or if there is a BIF (a built-in function implemented in C) + with the specified name, otherwise returns false.

+ +

This function used to return false for BIFs + before Erlang/OTP 18.0.

+
- Forces an immediate garbage collection of the calling process. + Force an immediate garbage collection of the calling process. +

Forces an immediate garbage collection of the executing process. The function is not to be used unless @@ -1563,73 +1580,76 @@ true - Garbage collects a process. + Garbage collect a process.

The same as - garbage_collect(Pid, []).

+ + garbage_collect(Pid, []).

- Garbage collects a process. + Garbage collect a process.

Garbage collects the node local process identified by - Pid.

-

The available Options are as follows:

+ Pid.

+

Option:

{async, RequestId} The function garbage_collect/2 returns - the value async immediately after the request - has been sent. When the request has been processed, the - process that called this function is passed a message on + the value async immediately after the request + has been sent. When the request has been processed, the + process that called this function is passed a message on the form {garbage_collect, RequestId, GCResult}. -

If Pid equals self(), and - no async option has been passed, the garbage - collection is performed at once, that is, the same as calling - garbage_collect/0. - Otherwise a request for garbage collection - is sent to the process identified by Pid, - and will be handled when appropriate. If no async - option has been passed, the caller blocks until - GCResult is available and can be returned.

-

GCResult informs about the result of - the garbage collection request as follows:

+

If Pid equals self(), and + no async option has been passed, the garbage + collection is performed at once, that is, the same as calling + + garbage_collect/0. + Otherwise a request for garbage collection + is sent to the process identified by Pid, + and will be handled when appropriate. If no async + option has been passed, the caller blocks until + GCResult is available and can be returned.

+

GCResult informs about the result of + the garbage collection request as follows:

true - The process identified by Pid has - been garbage collected. - + The process identified by Pid has + been garbage collected. + false - No garbage collection was performed, as - the process identified by Pid - terminated before the request could be satisfied. - + No garbage collection was performed, as + the process identified by Pid + terminated before the request could be satisfied. +

Notice that the same caveats apply as for - garbage_collect/0.

+ + garbage_collect/0.

Failures:

badarg - If Pid is not a node local process identifier. - + If Pid is not a node local process identifier. + badarg - If OptionList is an invalid list of options. - + If OptionList is an invalid list of options. +
- Returns the process dictionary. + Return the process dictionary.

Returns the process dictionary as a list of {Key, Val} tuples, for example:

@@ -1644,12 +1664,11 @@ true - Returns a value from the process dictionary. + Return a value from the process dictionary. -

Returns the value Val associated with Key in - the process dictionary, or undefined if Key - does not exist.

-

Example:

+

Returns the value Val associated with + Key in the process dictionary, or undefined + if Key does not exist. Example:

 > put(key1, merry),
 put(key2, lambs),
@@ -1661,7 +1680,7 @@ true
- Gets the magic cookie of the local node. + Get the magic cookie of the local node.

Returns the magic cookie of the local node if the node is alive, otherwise the atom nocookie.

@@ -1670,9 +1689,11 @@ true - Return a list of all keys from the process dictionary + Return a list of all keys from the process dictionary. + -

Returns a list of keys all keys present in the process dictionary.

+

Returns a list of all keys present in the process dictionary, + for example:

 > put(dog, {animal,1}),
 put(cow, {animal,2}),
@@ -1681,9 +1702,10 @@ true
[dog,cow,lamb]
+ - Returns a list of keys from the process dictionary. + Return a list of keys from the process dictionary.

Returns a list of keys that are associated with the value Val in the process dictionary, for example:

@@ -1701,48 +1723,49 @@ true - Gets the call stack back-trace of the last exception. + Get the call stack back-trace of the last exception.

Gets the call stack back-trace (stacktrace) of the last exception in the calling process as a list of - {Module,Function,Arity,Location} tuples. - Field Arity in the first tuple can be the + {Module,Function,Arity,Location} + tuples. Field Arity in the first tuple can be the argument list of that function call instead of an arity integer, depending on the exception.

If there has not been any exceptions in a process, the stacktrace is []. After a code change for the process, the stacktrace can also be reset to [].

-

The stacktrace is the same data as the catch operator +

The stacktrace is the same data as operator catch returns, for example:

-

{'EXIT',{badarg,Stacktrace}} = catch abs(x)

-

Location is a (possibly empty) list +

+{'EXIT',{badarg,Stacktrace}} = catch abs(x)
+

Location is a (possibly empty) list of two-tuples that - can indicate the location in the source code of the function. - The first element is an atom describing the type of - information in the second element. The following - items can occur:

- - file - The second element of the tuple is a string (list of - characters) representing the file name of the source file - of the function. - - line - The second element of the tuple is the line number - (an integer greater than zero) in the source file - where the exception occurred or the function was called. - - + can indicate the location in the source code of the function. + The first element is an atom describing the type of + information in the second element. The following + items can occur:

+ + file + The second element of the tuple is a string (list of + characters) representing the filename of the source file + of the function. + + line + The second element of the tuple is the line number + (an integer > 0) in the source file + where the exception occurred or the function was called. + +

See also - erlang:error/1 and - erlang:error/2.

+ error/1 and + error/2.

- Gets the group leader for the calling process. + Get the group leader for the calling process.

Returns the process identifier of the group leader for the process evaluating the function.

@@ -1750,14 +1773,14 @@ true groups have a group leader. All I/O from the group is channeled to the group leader. When a new process is spawned, it gets the same group leader as the spawning - process. Initially, at system start-up, init is both + process. Initially, at system startup, init is both its own group leader and the group leader of all processes.

- Sets the group leader for a process. + Set the group leader for a process.

Sets the group leader of Pid to GroupLeader. @@ -1765,72 +1788,72 @@ true certain shell is to have another group leader than init.

See also - group_leader/0.

+ group_leader/0.

- Halts the Erlang runtime system and indicates normal exit to the calling environment. + Halt the Erlang runtime system and indicate normal exit to + the calling environment. -

The same as - halt(0, []).

-

Example:

+

The same as + halt(0, []). Example:

 > halt().
-os_prompt% 
+os_prompt%
- Halts the Erlang runtime system. + Halt the Erlang runtime system. -

The same as - halt(Status, []).

-

Example:

+

The same as + halt(Status, []). Example:

 > halt(17).
 os_prompt% echo $?
 17
-os_prompt% 
+os_prompt%
- Halts the Erlang runtime system. + Halt the Erlang runtime system.

Status must be a non-negative integer, a string, - or the atom abort. - Halts the Erlang runtime system. Has no return value. - Depending on Status, the following occurs:

- - integer() - The runtime system exits with integer value - Status - as status code to the calling environment (OS). - - string() - An Erlang crash dump is produced with Status - as slogan. Then the runtime system exits with status code 1. - Note that only code points in the range 0-255 may be used - and the string will be truncated if longer than 200 characters. - - abort - - The runtime system aborts producing a core dump, if that is - enabled in the OS. - - -

On many platforms, the OS supports only status - codes 0-255. A too large status code will be truncated by clearing - the high bits.

-

For integer Status, the Erlang runtime system + or the atom abort. + Halts the Erlang runtime system. Has no return value. + Depending on Status, the following occurs:

+ + integer() + The runtime system exits with integer value + Status + as status code to the calling environment (OS). + + string() + An Erlang crash dump is produced with Status + as slogan. Then the runtime system exits with status code 1. + Note that only code points in the range 0-255 may be used + and the string will be truncated if longer than 200 characters. + + abort + The runtime system aborts producing a core dump, if that is + enabled in the OS. + + + +

On many platforms, the OS supports only status + codes 0-255. A too large status code is truncated by clearing + the high bits.

+
+

For integer Status, the Erlang runtime system closes all ports and allows async threads to finish their operations before exiting. To exit without such flushing, use - Option as {flush,false}.

-

For statuses string() and abort, option + Option as {flush,false}.

+

For statuses string() and abort, option flush is ignored and flushing is not done.

@@ -1842,13 +1865,15 @@ os_prompt%

Returns a hash value for Term within the range 1..Range. The maximum range is 1..2^27-1.

-

This BIF is deprecated, as the hash value can differ on - different architectures. The hash values for integer - terms higher than 2^27 and large binaries are +

This BIF is deprecated, as the hash value can differ on + different architectures. The hash values for integer + terms > 2^27 and large binaries are poor. The BIF is retained for backward compatibility reasons (it can have been used to hash records into a file), but all new code is to use one of the BIFs - erlang:phash/2 or erlang:phash2/1,2 instead.

+ erlang:phash/2 or + erlang:phash2/1,2 + instead.

@@ -1870,7 +1895,7 @@ os_prompt% - Hibernates a process until a message is sent to it. + Hibernate a process until a message is sent to it.

Puts the calling process into a wait state where its memory allocation has been reduced as much as possible. This is @@ -1878,15 +1903,15 @@ os_prompt% soon.

The process is awaken when a message is sent to it, and control resumes in Module:Function with - the arguments given by Args with the call + the arguments specified by Args with the call stack emptied, meaning that the process terminates when that function returns. Thus erlang:hibernate/3 never returns to its caller.

If the process has any message in its message queue, the process is awakened immediately in the same way as described earlier.

-

In more technical terms, what erlang:hibernate/3 does - is the following. It discards the call stack for the process, +

In more technical terms, erlang:hibernate/3 + discards the call stack for the process, and then garbage collects the process. After this, all live data is in one continuous heap. The heap is then shrunken to the exact same size as the live data @@ -1898,11 +1923,12 @@ os_prompt% size is changed to a size not smaller than the minimum heap size.

Notice that emptying the call stack means that any surrounding - catch is removed and must be reinserted after + catch is removed and must be re-inserted after hibernation. One effect of this is that processes started using proc_lib (also indirectly, such as gen_server processes), are to use - proc_lib:hibernate/3 + + proc_lib:hibernate/3 in STDLIB instead, to ensure that the exception handler continues to work when the process wakes up.

@@ -1910,15 +1936,16 @@ os_prompt% - Inserts an element at index in a tuple. - 1..tuple_size(Tuple1) + 1 + Insert an element at index in a tuple. + 1..tuple_size(Tuple1) + + 1

Returns a new tuple with element Term - inserted at position - Index in tuple Tuple1. - All elements from position Index and upwards are - pushed one step higher in the new tuple Tuple2.

-

Example:

+ inserted at position + Index in tuple Tuple1. + All elements from position Index and upwards are + pushed one step higher in the new tuple Tuple2. + Example:

 > erlang:insert_element(2, {one, two, three}, new).
 {one,new,two,three}
@@ -1942,8 +1969,8 @@ os_prompt% Text representation of an integer.

Returns a binary corresponding to the text - representation of Integer in base - Base, for example:

+ representation of Integer in base + Base, for example:

 > integer_to_binary(1023, 16).
 <<"3FF">>
@@ -1979,7 +2006,7 @@ os_prompt% Size of an iolist. -

Returns an integer that is the size in bytes +

Returns an integer, that is the size in bytes, of the binary that would be the result of iolist_to_binary(Item), for example:

@@ -1990,7 +2017,7 @@ os_prompt% 
- Converts an iolist to a binary. + Convert an iolist to a binary.

Returns a binary that is made from the integers and binaries in IoListOrBinary, for example:

@@ -2008,7 +2035,7 @@ os_prompt% - Checks whether the local node is alive. + Check whether the local node is alive.

Returns true if the local node is alive (that is, if the node can be part of a distributed system), otherwise @@ -2018,7 +2045,7 @@ os_prompt% - Checks whether a term is an atom. + Check whether a term is an atom.

Returns true if Term is an atom, otherwise false.

@@ -2028,18 +2055,18 @@ os_prompt% - Checks whether a term is a binary. + Check whether a term is a binary.

Returns true if Term is a binary, otherwise false.

-

A binary always contains a complete number of bytes.

+

A binary always contains a complete number of bytes.

Allowed in guard tests.

- Checks whether a term is a bitstring. + Check whether a term is a bitstring.

Returns true if Term is a bitstring (including a binary), otherwise false.

@@ -2049,7 +2076,7 @@ os_prompt% - Checks whether a term is a boolean. + Check whether a term is a boolean.

Returns true if Term is the atom true or the atom false (that is, a boolean). @@ -2060,18 +2087,18 @@ os_prompt% - Checks if a function is a BIF implemented in C. + Check if a function is a BIF implemented in C.

This BIF is useful for builders of cross-reference tools.

Returns true if Module:Function/Arity - is a BIF implemented in C, otherwise false.

+ is a BIF implemented in C, otherwise false.

- Checks whether a term is a float. + Check whether a term is a float.

Returns true if Term is a floating point number, otherwise false.

@@ -2081,7 +2108,7 @@ os_prompt% - Checks whether a term is a fun. + Check whether a term is a fun.

Returns true if Term is a fun, otherwise false.

@@ -2091,7 +2118,8 @@ os_prompt% - Checks whether a term is a fun with a given arity. + Check whether a term is a fun with a specified given arity. +

Returns true if Term is a fun that can be applied with Arity number of arguments, otherwise @@ -2102,7 +2130,7 @@ os_prompt% - Checks whether a term is an integer. + Check whether a term is an integer.

Returns true if Term is an integer, otherwise false.

@@ -2112,7 +2140,7 @@ os_prompt% - Checks whether a term is a list. + Check whether a term is a list.

Returns true if Term is a list with zero or more elements, otherwise false.

@@ -2122,7 +2150,7 @@ os_prompt% - Checks whether a term is a map. + Check whether a term is a map.

Returns true if Term is a map, otherwise false.

@@ -2132,7 +2160,7 @@ os_prompt% - Checks whether a term is a number. + Check whether a term is a number.

Returns true if Term is an integer or a floating point number. Otherwise returns false.

@@ -2142,7 +2170,7 @@ os_prompt% - Checks whether a term is a process identifier. + Check whether a term is a process identifier.

Returns true if Term is a process identifier, otherwise false.

@@ -2152,7 +2180,7 @@ os_prompt% - Checks whether a term is a port. + Check whether a term is a port.

Returns true if Term is a port identifier, otherwise false.

@@ -2162,26 +2190,26 @@ os_prompt% - Checks whether a process is alive. + Check whether a process is alive. -

Pid must refer to a process at the local node.

+

Pid must refer to a process at the local + node.

Returns true if the process exists and is alive, that is, is not exiting and has not exited. Otherwise returns - false. -

+ false.

- Checks whether a term appears to be a record. + Check whether a term appears to be a record.

Returns true if Term is a tuple and its first element is RecordTag. Otherwise returns false.

Normally the compiler treats calls to is_record/2 - specially. It emits code to verify that Term + especially. It emits code to verify that Term is a tuple, that its first element is RecordTag, and that the size is correct. However, if RecordTag is @@ -2195,7 +2223,7 @@ os_prompt% - Checks whether a term appears to be a record. + Check whether a term appears to be a record.

RecordTag must be an atom.

Returns true if @@ -2214,7 +2242,7 @@ os_prompt% - Checks whether a term is a reference. + Check whether a term is a reference.

Returns true if Term is a reference, otherwise false.

@@ -2224,7 +2252,7 @@ os_prompt% - Checks whether a term is a tuple. + Check whether a term is a tuple.

Returns true if Term is a tuple, otherwise false.

@@ -2246,7 +2274,7 @@ os_prompt% - Creates a link to another process (or port). + Create a link to another process (or port).

Creates a link between the calling process and another process (or port) PidOrPort, if there is @@ -2256,34 +2284,34 @@ os_prompt%

If PidOrPort does not exist, the behavior of the BIF depends on if the calling process is trapping exits or not (see - process_flag/2):

+ + process_flag/2):

- If the calling process is not trapping exits, and - checking PidOrPort is cheap - (that is, if PidOrPort - is local), link/1 fails with reason noproc. - Otherwise, if the calling process is trapping exits, - and/or PidOrPort is remote, link/1 - returns true, but an exit signal with reason noproc - is sent to the calling process. +

If the calling process is not trapping exits, and + checking PidOrPort is cheap + (that is, if PidOrPort + is local), link/1 fails with reason noproc.

+

Otherwise, if the calling process is trapping exits, + and/or PidOrPort is remote, link/1 + returns true, but an exit signal with reason noproc + is sent to the calling process.

- Converts from text representation to an atom. + Convert from text representation to an atom.

Returns the atom whose text representation is String.

-

String can only contain ISO-latin-1 - characters (that is, - numbers less than 256) as the implementation does not - allow unicode characters equal to or above 256 in atoms. - For more information on Unicode support in atoms, see - note on UTF-8 +

String can only contain ISO-latin-1 + characters (that is, numbers < 256) as the implementation does not + allow Unicode characters equal to or above 256 in atoms. + For more information on Unicode support in atoms, see + note on UTF-8 encoded atoms - in Section "External Term Format" in the User's Guide.

+ in section "External Term Format" in the User's Guide.

Example:

 > list_to_atom("Erlang").
@@ -2293,7 +2321,7 @@ os_prompt% 
- Converts a list to a binary. + Convert a list to a binary.

Returns a binary that is made from the integers and binaries in IoList, for example:

@@ -2311,13 +2339,13 @@ os_prompt% - Converts a list to a bitstring. + Convert a list to a bitstring.

Returns a bitstring that is made from the integers and bitstrings in BitstringList. (The last tail in - BitstringList is allowed to be a bitstring.)

-

Example:

+ BitstringList is allowed to be a bitstring.) + Example:

 > Bin1 = <<1,2,3>>.
 <<1,2,3>>
@@ -2332,7 +2360,7 @@ os_prompt% 
- Converts from text representation to an atom. + Convert from text representation to an atom.

Returns the atom whose text representation is String, @@ -2344,7 +2372,7 @@ os_prompt% - Converts from text representation to a float. + Convert from text representation to a float.

Returns the float whose text representation is String, for example:

@@ -2358,7 +2386,7 @@ os_prompt% - Converts from text representation to an integer. + Convert from text representation to an integer.

Returns an integer whose text representation is String, for example:

@@ -2372,7 +2400,7 @@ os_prompt% - Converts from text representation to an integer. + Convert from text representation to an integer.

Returns an integer whose text representation in base Base is String, @@ -2387,7 +2415,7 @@ os_prompt% - Converts from text representation to a pid. + Convert from text representation to a pid.

Returns a process identifier whose text representation is a String, for example:

@@ -2398,14 +2426,14 @@ os_prompt% representation of a process identifier.

This BIF is intended for debugging and is not to be used - in application programs.

+ in application programs.

- Converts a list to a tuple. + Convert a list to a tuple.

Returns a tuple corresponding to List, for example

@@ -2418,7 +2446,7 @@ os_prompt% - Loads object code for a module. + Load object code for a module.

If Binary contains the object code for module Module, this BIF loads that object code. If @@ -2429,23 +2457,21 @@ os_prompt% that code.

Returns either {module, Module}, or {error, Reason} if loading fails. - Reason is any of the following:

+ Reason is one of the following:

badfile - -

The object code in Binary has an - incorrect format or the object code contains code - for another module than Module.

+ The object code in Binary has an + incorrect format or the object code contains code + for another module than Module. not_purged - -

Binary contains a module that cannot be - loaded because old code for this module already exists.

+ Binary contains a module that cannot be + loaded because old code for this module already exists.

This BIF is intended for the code server (see - code(3)) + kernel:code(3)) and is not to be used elsewhere.

@@ -2453,33 +2479,33 @@ os_prompt% - Loads NIF library. + Load NIF library. -

Before OTP R14B, NIFs were an - experimental feature. Versions before OTP R14B can - have different and possibly incompatible NIF semantics and - interfaces. For example, in OTP R13B03 the return value on - failure was {error,Reason,Text}.

+

Before Erlang/OTP R14B, NIFs were an + experimental feature. Versions before Erlang/OTP R14B can + have different and possibly incompatible NIF semantics and + interfaces. For example, in Erlang/OTP R13B03 the return value on + failure was {error,Reason,Text}.

Loads and links a dynamic library containing native - implemented functions (NIFs) for a module. Path - is a file path to the shareable object/dynamic library file minus - the OS-dependent file extension (.so for Unix and - .dll for Windows. For information on how to - implement a NIF library, see - erl_nif.

+ implemented functions (NIFs) for a module. Path + is a file path to the shareable object/dynamic library file minus + the OS-dependent file extension (.so for Unix and + .dll for Windows). For information on how to + implement a NIF library, see + erl_nif.

LoadInfo can be any term. It is passed on to - the library as part of the initialization. A good practice is - to include a module version number to support future code - upgrade scenarios.

+ the library as part of the initialization. A good practice is + to include a module version number to support future code + upgrade scenarios.

The call to load_nif/2 must be made - directly from the Erlang code of the module that the - NIF library belongs to. It returns either ok, or - {error,{Reason,Text}} if loading fails. - Reason is one of the following atoms - while Text is a human readable string that - can give more information about the failure:

+ directly from the Erlang code of the module that the + NIF library belongs to. It returns either ok, or + {error,{Reason,Text}} if loading fails. + Reason is one of the following atoms + while Text is a human readable string that + can give more information about the failure:

load_failed The OS failed to load the NIF library. @@ -2502,11 +2528,12 @@ os_prompt% - Lists all loaded modules. + List all loaded modules.

Returns a list of all loaded Erlang modules (current and old code), including preloaded modules.

-

See also code(3).

+

See also + kernel:code(3).

@@ -2527,13 +2554,13 @@ os_prompt% - Converts from local to Universal Time Coordinated (UTC) date and time. + Convert from local to Universal Time Coordinated (UTC) date + and time.

Converts local date and time to Universal Time Coordinated (UTC), if supported by the underlying OS. Otherwise no conversion is done and Localtime - is returned.

-

Example:

+ is returned. Example:

 > erlang:localtime_to_universaltime({{1996,11,6},{14,45,17}}).
 {{1996,11,6},{13,45,17}}
@@ -2544,15 +2571,16 @@ os_prompt% - Converts from local to Universal Time Coordinated (UTC) date and time. + Convert from local to Universal Time Coordinated (UTC) date + and time.

Converts local date and time to Universal Time Coordinated (UTC) as erlang:localtime_to_universaltime/1, but the caller decides if Daylight Saving Time is active.

-

If IsDst == true, Localtime is - during Daylight Saving Time, if IsDst == false it is - not. If IsDst == undefined, the underlying OS can - guess, which is the same as calling +

If IsDst == true, Localtime + is during Daylight Saving Time, if IsDst == false + it is not. If IsDst == undefined, the underlying + OS can guess, which is the same as calling erlang:localtime_to_universaltime(Localtime).

Examples:

@@ -2569,24 +2597,27 @@ os_prompt% 
- Returns a unique reference. + Return a unique reference. -

Returns a unique - reference. The reference is unique among - connected nodes.

-

Known issue: When a node is restarted multiple - times with the same node name, references created - on a newer node can be mistaken for a reference - created on an older node with the same node name.

+

Returns a + + unique reference. The reference is unique among + connected nodes.

+ +

Known issue: When a node is restarted multiple + times with the same node name, references created + on a newer node can be mistaken for a reference + created on an older node with the same node name.

+
- Creates a new tuple of a given arity. + Create a new tuple of a specified arity. -

Creates a new tuple of the given Arity, where all - elements are InitialValue, for example:

+

Creates a new tuple of the specified Arity, where + all elements are InitialValue, for example:

 > erlang:make_tuple(4, []).
 {[],[],[],[]}
@@ -2595,17 +2626,16 @@ os_prompt% - Creates a new tuple with given arity and contents. + Create a new tuple with specifed arity and contents.

Creates a tuple of size Arity, where each element has value DefaultValue, and then fills in - values from InitList. + values from InitList. Each list element in InitList - must be a two-tuple, where the first element is a position in the - newly created tuple and the second element is any term. If a - position occurs more than once in the list, the term corresponding - to the last occurrence is used.

-

Example:

+ must be a two-tuple, where the first element is a position in the + newly created tuple and the second element is any term. If a + position occurs more than once in the list, the term corresponding + to the last occurrence is used. Example:

 > erlang:make_tuple(5, [], [{2,ignored},{5,zz},{2,aa}]).
 {{[],aa,[],[],zz}
@@ -2614,7 +2644,7 @@ os_prompt% - Returns the size of a map. + Return the size of a map.

Returns an integer, which is the number of key-value pairs in Map, for example:

@@ -2627,74 +2657,75 @@ os_prompt% - Test that a match specification works - -

- This function is a utility to test a match_spec used in calls to - ets:select/2 and - erlang:trace_pattern/3. - The function both tests MatchSpec for "syntactic" correctness and - runs the match_spec against the object. If the match_spec contains - errors, the tuple {error, Errors} is returned where Errors is a list - of natural language descriptions of what was wrong with the match_spec. -

-

- If the Type is table the object to match - against should be a tuple. The function then returns - {ok,Result,[],Warnings} where Result is what would have been the - result in a real ets:select/2 call or false if the match_spec does - not match the object tuple. -

- -

- If Type is trace the object to match - against should be a list. The function returns - {ok, Result, Flags, Warnings} where Result is true if a trace - message should be emitted, false if a trace message should not - be emitted or the message term to be appended to the trace message. - Flags is a list containing all the trace flags that will be enabled, - at the moment this is only return_trace. -

- -

- This is a useful debugging and test tool, especially when writing complicated - match specifications. -

-

- See also - ets:test_ms/2. -

+ Test that a match specification works. + +

Tests a match specification used in calls to + ets:select/2 + and + erlang:trace_pattern/3. + The function tests both a match specification for "syntactic" + correctness and runs the match specification against the object. If + the match specification contains errors, the tuple {error, + Errors} is returned, where Errors is a list of natural + language descriptions of what was wrong with the match + specification.

+

If Type is table, the object to match + against is to be a tuple. The function then returns + {ok,Result,[],Warnings}, where Result is what would + have been the result in a real ets:select/2 call, or + false if the match specification does not match the object + tuple.

+

If Type is trace, the object to match + against is to be a list. The function returns + {ok, Result, Flags, Warnings}, where Result is one of + the following:

+ + true if a trace message is to be emitted + false if a trace message is not to be emitted + The message term to be appended to the trace message + +

Flags is a list containing all the trace flags to be enabled, + currently this is only return_trace.

+

This is a useful debugging and test tool, especially when writing + complicated match specifications.

+

See also + ets:test_ms/2 + in STDLIB.

- Returns the largest of two terms. + Return the largest of two terms.

Returns the largest of Term1 and Term2. - If the terms are equal, Term1 is returned.

+ If the terms are equal, Term1 is returned.

- Computes an MD5 message digest. + Compute an MD5 message digest.

Computes an MD5 message digest from Data, where the length of the digest is 128 bits (16 bytes). Data is a binary or a list of small integers and binaries.

-

For more information about MD5, see RFC 1321 - The - MD5 Message-Digest Algorithm.

-

The MD5 Message-Digest Algorithm is not considered - safe for code-signing or software-integrity purposes.

+

For more information about MD5, see + + RFC 1321 - The MD5 Message-Digest Algorithm.

+ +

The MD5 Message-Digest Algorithm is not considered + safe for code-signing or software-integrity purposes.

+
- Finishes the update of an MD5 context and returns the computed MD5 message digest. + Finish the update of an MD5 context and return the computed + MD5 message digest.

Finishes the update of an MD5 Context and returns the computed MD5 message digest.

@@ -2703,18 +2734,19 @@ os_prompt% - Creates an MD5 context. + Create an MD5 context. -

Creates an MD5 context, to be used in subsequent calls to +

Creates an MD5 context, to be used in the following calls to md5_update/2.

- Updates an MD5 context with data and returns a new context. + Update an MD5 context with data and return a new context. + -

Updates an MD5 Context with +

Update an MD5 Context with Data and returns a NewContext.

@@ -2730,7 +2762,7 @@ os_prompt% element is a tuple {Type, Size}. The first element Type is an atom describing memory type. The second element Size is the memory size in bytes.

-

The memory types are as follows:

+

Memory types:

total @@ -2782,7 +2814,7 @@ os_prompt% ets -

The total amount of memory currently allocated for ets +

The total amount of memory currently allocated for ets tables. This memory is part of the memory presented as system memory.

@@ -2790,9 +2822,9 @@ os_prompt%

Only on 64-bit halfword emulator. The total amount of memory allocated in low memory areas - that are restricted to less than 4 GB, although - the system can have more memory.

-

Can be removed in a future release of the halfword + that are restricted to < 4 GB, although + the system can have more memory.

+

Can be removed in a future release of the halfword emulator.

maximum @@ -2802,8 +2834,9 @@ os_prompt% when the emulator is run with instrumentation.

For information on how to run the emulator with instrumentation, see - instrument(3) - and/or erl(1).

+ + tools:instrument(3) + and/or erl(1).

@@ -2820,20 +2853,20 @@ os_prompt%

As the total value is the sum of processes and system, the error in system propagates to the total value.

-

The different amounts of memory that are summed are - not gathered atomically, which introduces - an error in the result.

+

The different amounts of memory that are summed are + not gathered atomically, which introduces + an error in the result.

The different values have the following relation to each other. Values beginning with an uppercase letter is not part of the result.

- total = processes + system - processes = processes_used + ProcessesNotUsed - system = atom + binary + code + ets + OtherSystem - atom = atom_used + AtomNotUsed - RealTotal = processes + RealSystem - RealSystem = system + MissedSystem +total = processes + system +processes = processes_used + ProcessesNotUsed +system = atom + binary + code + ets + OtherSystem +atom = atom_used + AtomNotUsed +RealTotal = processes + RealSystem +RealSystem = system + MissedSystem

More tuples in the returned list can be added in a future release.

@@ -2843,20 +2876,20 @@ os_prompt% the emulator stacks are not supposed to be included. That is, the total value is not supposed to be equal to the total size of all pages mapped to the emulator.

-

Furthermore, because of fragmentation and prereservation of +

Also, because of fragmentation and prereservation of memory areas, the size of the memory segments containing the dynamically allocated memory blocks can be much larger than the total size of the dynamically allocated memory blocks.

- -

As from ERTS 5.6.4, erlang:memory/0 requires that - all erts_alloc(3) - allocators are enabled (default behavior).

-
+ +

As from ERTS 5.6.4, erlang:memory/0 requires that + all erts_alloc(3) + allocators are enabled (default behavior).

+

Failure: notsup if an - erts_alloc(3) - allocator has been disabled.

+ erts_alloc(3) + allocator has been disabled.

@@ -2866,61 +2899,61 @@ os_prompt% Information about dynamically allocated memory. -

Returns the memory size in bytes allocated for memory of - type Type. The argument can also be given as a list +

Returns the memory size in bytes allocated for memory of type + Type. The argument can also be specifed as a list of memory_type() atoms, in which case a corresponding list of {memory_type(), Size :: integer >= 0} tuples is returned.

- -

As from ERTS version 5.6.4, + +

As from ERTS 5.6.4, erlang:memory/1 requires that - all erts_alloc(3) - allocators are enabled (default behavior).

-
+ all erts_alloc(3) + allocators are enabled (default behavior).

+

Failures:

badarg - If Type is not one of the memory types + If Type is not one of the memory types listed in the description of - erlang:memory/0. - + erlang:memory/0. + badarg - If maximum is passed as Type and + If maximum is passed as Type and the emulator is not run in instrumented mode. - + notsup - If an erts_alloc(3) - allocator has been disabled. - - + If an erts_alloc(3) + allocator has been disabled. + +

See also - erlang:memory/0.

+ erlang:memory/0.

- Returns the smallest of two terms. + Return the smallest of two terms.

Returns the smallest of Term1 and Term2. - If the terms are equal, Term1 is returned.

+ If the terms are equal, Term1 is returned.

- Checks if a module is loaded. + Check if a module is loaded.

Returns true if the module Module is loaded, otherwise false. It does not attempt to load the module.

This BIF is intended for the code server (see - code(3)) and is not to be - used elsewhere.

+ kernel:code(3)) + and is not to be used elsewhere.

@@ -2929,7 +2962,7 @@ os_prompt% - Starts monitoring. + Start monitoring. @@ -2937,35 +2970,39 @@ os_prompt%

Sends a monitor request of type Type to the entity identified by Item. If the monitored entity - does not exist or when it dies, the caller of monitor/2 will - be notified by a message on the following format:

- {Tag, MonitorRef, Type, Object, Info} -

The monitor request is an asynchronous signal. That is, it - takes time before the signal reaches its destination.

+ does not exist or it changes monitored state, the caller of + monitor/2 is notified by a message on the following format:

+ +{Tag, MonitorRef, Type, Object, Info} + +

The monitor request is an asynchronous signal. That is, it + takes time before the signal reaches its destination.

+

Type can be one of the following atoms: process, port or time_offset.

-

A monitor is triggered only once, after that it is removed from - both monitoring process and the monitored entity. - Monitors are fired when the monitored process or port terminates, - does not exist at the moment of creation, or if the connection to - it is lost. In the case with connection, we lose knowledge about - the fact if it still exists or not. The monitoring is also turned off - when demonitor/1 - is called.

- -

When monitoring by name please note, that the RegisteredName - is resolved to pid() or port() only once - at the moment of monitor instantiation, later changes to the name - registration will not affect the existing monitor.

- -

When a monitor is triggered, a 'DOWN' message that has the - following pattern {'DOWN', MonitorRef, Type, Object, Info} - is sent to the monitoring process.

- -

In monitor message MonitorRef and Type are the same as - described earlier, and:

+

A process or port monitor is triggered only once, + after that it is removed from both monitoring process and + the monitored entity. Monitors are fired when the monitored process + or port terminates, does not exist at the moment of creation, + or if the connection to it is lost. If the connection to it is lost, + we do not know if it still exixts. The monitoring is also turned off + when demonitor/1 is + called.

+ +

A process or port monitor by name + resolves the RegisteredName to pid() or port() + only once at the moment of monitor instantiation, later changes to + the name registration will not affect the existing monitor.

+ +

When a process or port monitor is triggered, + a 'DOWN' message is sent that has the following pattern:

+ +{'DOWN', MonitorRef, Type, Object, Info} + +

In the monitor message MonitorRef and Type are the + same as described earlier, and:

Object @@ -2992,14 +3029,14 @@ os_prompt% implemented), the call fails with badarg.

The format of the 'DOWN' message changed in ERTS - version 5.2 (OTP R9B) for monitoring + 5.2 (Erlang/OTP R9B) for monitoring by registered name. Element Object of the 'DOWN' message could in earlier versions sometimes be the process identifier of the monitored process and sometimes be the registered name. Now element Object is always a tuple consisting of the registered name and - the node name. Processes on new nodes (ERTS version 5.2 - or higher) always get 'DOWN' messages on + the node name. Processes on new nodes (ERTS 5.2 + or higher versions) always get 'DOWN' messages on the new format even if they are monitoring processes on old nodes. Processes on old nodes always get 'DOWN' messages on the old format.

@@ -3008,11 +3045,11 @@ os_prompt% Monitoring a process -

Creates monitor between the current process and another - process identified by Item, which can be a - pid() (local or remote), an atom RegisteredName or - a tuple {RegisteredName, Node} for a registered process, - located elsewhere.

+

Creates monitor between the current process and another + process identified by Item, which can be a + pid() (local or remote), an atom RegisteredName or + a tuple {RegisteredName, Node} for a registered process, + located elsewhere.

Monitoring a port @@ -3026,62 +3063,64 @@ os_prompt%
Monitoring a - time_offset + time_offset -

Monitor changes in - time offset - between - Erlang - monotonic time and - Erlang - system time. There is only one valid - Item in combination with the - time_offset Type, namely the atom - clock_service. Note that the atom clock_service is - not the registered name of a process. In this specific - case it serves as an identifier of the runtime system internal - clock service at current runtime system instance.

+

Monitors changes in + time offset + between + Erlang + monotonic time and + Erlang + system time. One valid Item + exists in combination with the + time_offset Type, namely the atom + clock_service. Notice that the atom clock_service is + not the registered name of a process. In this + case it serves as an identifier of the runtime system internal + clock service at current runtime system instance.

The monitor is triggered when the time offset is changed. - This either if the time offset value is changed, or if the - offset is changed from preliminary to final during - finalization - of the time offset when the - single - time warp mode is used. When a change from preliminary - to final time offset is made, the monitor will be triggered once - regardless of whether the time offset value was actually changed - or not.

+ This either if the time offset value is changed, or if the + offset is changed from preliminary to final during + finalization + of the time offset when the + single + time warp mode is used. When a change from preliminary + to final time offset is made, the monitor is triggered once + regardless of whether the time offset value was changed + or not.

If the runtime system is in - multi - time warp mode, the time offset will be changed when - the runtime system detects that the - OS system - time has changed. The runtime system will, however, - not detect this immediately when it happens. A task checking - the time offset is scheduled to execute at least once a minute, - so under normal operation this should be detected within a - minute, but during heavy load it might take longer time.

- -

The monitor will not be automatically removed - after it has been triggered. That is, repeated changes of - the time offset will trigger the monitor repeatedly.

- -

When the monitor is triggered a 'CHANGE' message will - be sent to the monitoring process. A 'CHANGE' message has - the following pattern:

- {'CHANGE', MonitorRef, Type, Item, NewTimeOffset} -

where MonitorRef, Type, and - Item are the same as described above, and - NewTimeOffset is the new time offset.

+ multi + time warp mode, the time offset is changed when + the runtime system detects that the + OS system + time has changed. The runtime system does, however, + not detect this immediately when it occurs. A task checking + the time offset is scheduled to execute at least once a minute, + so under normal operation this is to be detected within a + minute, but during heavy load it can take longer time.

+ +

The monitor is not automatically removed + after it has been triggered. That is, repeated changes of + the time offset trigger the monitor repeatedly.

+ +

When the monitor is triggered a 'CHANGE' message is + sent to the monitoring process. A 'CHANGE' message has + the following pattern:

+ +{'CHANGE', MonitorRef, Type, Item, NewTimeOffset} +

where MonitorRef, Type, and + Item are the same as described above, and + NewTimeOffset is the new time offset.

When the 'CHANGE' message has been received you are - guaranteed not to retrieve the old time offset when calling - erlang:time_offset(). - Note that you can observe the change of the time offset - when calling erlang:time_offset() before you - get the 'CHANGE' message.

+ guaranteed not to retrieve the old time offset when calling + + erlang:time_offset(). + Notice that you can observe the change of the time offset + when calling erlang:time_offset() before you + get the 'CHANGE' message.

@@ -3092,20 +3131,19 @@ os_prompt%

The monitor functionality is expected to be extended. That is, other Types and Items are expected to be supported in a future release.

-

If or when monitor/2 is extended, other - possible values for Tag, Object and - Info in the monitor message will be introduced.

+ possible values for Tag, Object, and + Info in the monitor message will be introduced.

- Monitors the status of a node. + Monitor the status of a node. -

Monitors the status of the node Node. +

Monitor the status of the node Node. If Flag is true, monitoring is turned on. If Flag is false, monitoring is turned off.

@@ -3127,12 +3165,12 @@ os_prompt% - Monitors the status of a node. + Monitor the status of a node.

Behaves as - monitor_node/2 + monitor_node/2 except that it allows an - extra option to be given, namely allow_passive_connect. + extra option to be specified, namely allow_passive_connect. This option allows the BIF to wait the normal network connection time-out for the monitored node to connect itself, even if it cannot be actively connected from this node @@ -3155,70 +3193,77 @@ os_prompt% Current Erlang monotonic time. -

Returns the current - Erlang - monotonic time in native - time unit. This - is a monotonically increasing time since some unspecified point in - time.

- -

This is a - monotonically increasing time, but not a - strictly monotonically increasing - time. That is, consecutive calls to - erlang:monotonic_time/0 can produce the same result.

- -

Different runtime system instances will use different - unspecified points in time as base for their Erlang monotonic clocks. - That is, it is pointless comparing monotonic times from - different runtime system instances. Different runtime system instances - may also place this unspecified point in time different relative - runtime system start. It may be placed in the future (time at start - is a negative value), the past (time at start is a - positive value), or the runtime system start (time at start is - zero). The monotonic time at runtime system start can be - retrieved by calling - erlang:system_info(start_time).

+

Returns the current + Erlang + monotonic time in native + time unit. This + is a monotonically increasing time since some unspecified point in + time.

+ +

This is a + + monotonically increasing time, but not a + + strictly monotonically increasing + time. That is, consecutive calls to + erlang:monotonic_time/0 can produce the same result.

+

Different runtime system instances will use different unspecified + points in time as base for their Erlang monotonic clocks. + That is, it is pointless comparing monotonic times from + different runtime system instances. Different runtime system + instances can also place this unspecified point in time different + relative runtime system start. It can be placed in the future (time + at start is a negative value), the past (time at start is a + positive value), or the runtime system start (time at start is + zero). The monotonic time at runtime system start can be + retrieved by calling + + erlang:system_info(start_time).

+
+ - Current Erlang monotonic time + Current Erlang monotonic time. -

Returns the current - Erlang - monotonic time converted - into the Unit passed as argument.

- -

Same as calling - erlang:convert_time_unit(erlang:monotonic_time(), - native, Unit) - however optimized for commonly used Units.

+

Returns the current + Erlang + monotonic time converted + into the Unit passed as argument.

+

Same as calling + + erlang:convert_time_unit( + erlang:monotonic_time(), + native, Unit), + however optimized for commonly used Units.

+ - Stops execution with a given reason. + Stop execution with a specifed reason.

Works exactly like - erlang:error/1, but - Dialyzer thinks that this BIF will return an arbitrary - term. When used in a stub function for a NIF to generate an - exception when the NIF library is not loaded, Dialyzer - does not generate false warnings.

+ error/1, but + Dialyzer thinks that this BIF will return an arbitrary + term. When used in a stub function for a NIF to generate an + exception when the NIF library is not loaded, Dialyzer + does not generate false warnings.

- Stops execution with a given reason. + Stop execution with a specified reason.

Works exactly like - erlang:error/2, but - Dialyzer thinks that this BIF will return an arbitrary - term. When used in a stub function for a NIF to generate an - exception when the NIF library is not loaded, Dialyzer - does not generate false warnings.

+ error/2, but + Dialyzer thinks that this BIF will return an arbitrary + term. When used in a stub function for a NIF to generate an + exception when the NIF library is not loaded, Dialyzer + does not generate false warnings.

@@ -3258,10 +3303,10 @@ os_prompt% All nodes of a certain type in the system. -

Returns a list of nodes according to the argument given. - The returned result when the argument is a list, is the list +

Returns a list of nodes according to the argument specified. + The returned result, when the argument is a list, is the list of nodes satisfying the disjunction(s) of the list elements.

-

NodeType can be any of the following:

+

NodeTypes:

visible @@ -3282,13 +3327,15 @@ os_prompt% known

Nodes that are known to this node. That is, connected - nodes and nodes referred to by process identifiers, port - identifiers and references located on this node. - The set of known nodes is garbage collected. Notice that - this garbage collection can be delayed. For more - information, see - delayed_node_table_gc. -

+ nodes and nodes referred to by process identifiers, port + identifiers, and references located on this node. + The set of known nodes is garbage collected. Notice that + this garbage collection can be delayed. For more + information, see + + delayed_node_table_gc in + + erlang:system_info/1.

Some equalities: [node()] = nodes(this), @@ -3302,20 +3349,22 @@ os_prompt% Elapsed time since 00:00 GMT. -

This function is deprecated! Do not use it! - See the users guide chapter - Time and Time Correction - for more information. Specifically the - Dos and Dont's - section for information on what to use instead of erlang:now/0. -

-

Returns the tuple {MegaSecs, Secs, MicroSecs} which is + +

This function is deprecated. Do not use it.

+

For more information, see section + Time and Time Correction + in the User's Guide. Specifically, section + + Dos and Dont's describes what to use instead of + erlang:now/0.

+ +

Returns the tuple {MegaSecs, Secs, MicroSecs}, which is the elapsed time since 00:00 GMT, January 1, 1970 (zero hour), - on the assumption that the underlying OS supports this. + if provided by the underlying OS. Otherwise some other point in time is chosen. It is also - guaranteed that subsequent calls to this BIF return + guaranteed that the following calls to this BIF return continuously increasing values. Hence, the return value from - now() can be used to generate unique time-stamps. + erlang:now/0 can be used to generate unique time stamps. If it is called in a tight loop on a fast machine, the time of the node can become skewed.

Can only be used to check the local time of day if @@ -3326,28 +3375,31 @@ os_prompt% - Opens a port. + Open a port.

Returns a port identifier as the result of opening a new Erlang port. A port can be seen as an external Erlang process.

-

The name of the executable as well as the arguments - given in cd, env, args, and arg0 are - subject to Unicode file name translation if the system is running - in Unicode file name mode. To avoid - translation or to force, for example UTF-8, supply the executable - and/or arguments as a binary in the correct - encoding. For details, see the module - file, the function - file:native_name_encoding/0, and the - STDLIB - User's Guide.

-

The characters in the name (if given as a list) can - only be higher than 255 if the Erlang Virtual Machine is started - in Unicode file name translation mode. Otherwise the name - of the executable is limited to the ISO-latin-1 - character set.

-

PortName can be any of the following:

+

The name of the executable as well as the arguments + specifed in cd, env, args, and arg0 are + subject to Unicode filename translation if the system is running + in Unicode filename mode. To avoid + translation or to force, for example UTF-8, supply the executable + and/or arguments as a binary in the correct + encoding. For details, see the module + kernel:file, the + function + file:native_name_encoding/0 in Kernel, and + the STDLIB + User's Guide.

+ +

The characters in the name (if specified as a list) can + only be > 255 if the Erlang virtual machine is started + in Unicode filename translation mode. Otherwise the name + of the executable is limited to the ISO Latin-1 + character set.

+
+

PortNames:

{spawn, Command} @@ -3366,55 +3418,57 @@ os_prompt% vfork, setting environment variable ERL_NO_VFORK to any value causes fork to be used instead.

-

For external programs, PATH is searched - (or an equivalent method is used to find programs, - depending on OS). This is done by invoking - the shell on certain platforms. The first space-separated - token of the command is considered as the - name of the executable (or driver). This (among other - things) makes this option unsuitable for running - programs having spaces in file names or directory names. - If spaces in executable file names are desired, use - {spawn_executable, Command} instead.

+

For external programs, PATH is searched + (or an equivalent method is used to find programs, + depending on the OS). This is done by invoking + the shell on certain platforms. The first space-separated + token of the command is considered as the + name of the executable (or driver). This (among other + things) makes this option unsuitable for running + programs with spaces in filenames or directory names. + If spaces in executable filenames are desired, use + {spawn_executable, Command} instead.

{spawn_driver, Command} -

Works like {spawn, Command}, 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 - badarg error is raised.

+

Works like {spawn, Command}, 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 + badarg error is raised.

{spawn_executable, FileName} -

Works like {spawn, FileName}, but only runs - external executables. FileName in its whole - is used as the name of the executable, including any spaces. - If arguments are to be passed, the PortSettings - args and arg0 can be used.

-

The shell is usually not invoked to start the - program, it is executed directly. PATH (or +

Works like {spawn, FileName}, but only runs + external executables. FileName in its whole + is used as the name of the executable, including any spaces. + If arguments are to be passed, the + PortSettings + args and arg0 can be used.

+

The shell is usually not invoked to start the + program, it is executed directly. PATH (or equivalent) is not searched. To find a program - in PATH to execute, use - os:find_executable/1.

-

Only if a shell script or .bat file is - executed, the appropriate command interpreter is - invoked implicitly, but there is still no - command argument expansion or implicit PATH search.

-

If FileName cannot be run, an error - exception is raised, with the POSIX error code as the reason. - The error reason can differ between OSs. - Typically the error enoent is raised when an - attempt is made to run a program that is not found and - eacces is raised when the given file is not - executable.

+ in PATH to execute, use + + os:find_executable/1.

+

Only if a shell script or .bat file is + executed, the appropriate command interpreter is + invoked implicitly, but there is still no + command-argument expansion or implicit PATH search.

+

If FileName cannot be run, an error + exception is raised, with the POSIX error code as the reason. + The error reason can differ between OSs. + Typically the error enoent is raised when an + attempt is made to run a program that is not found and + eacces is raised when the specified file is not + executable.

{fd, In, Out}

Allows an Erlang process to access any currently opened file descriptors used by Erlang. The file descriptor - In can be used for standard input, and the file - descriptor Out for standard output. It is only - used for various servers in the Erlang OS (shell + In can be used for standard input, and the + file descriptor Out for standard output. + It is only used for various servers in the Erlang OS (shell and user). Hence, its use is limited.

@@ -3423,7 +3477,8 @@ os_prompt% {packet, N} -

Messages are preceded by their length, sent in N +

Messages are preceded by their length, sent in + N bytes, with the most significant byte first. The valid values for N are 1, 2, and 4.

@@ -3436,16 +3491,16 @@ os_prompt% {line, L}

Messages are delivered on a per line basis. Each line - (delimited by the OS-dependent new line sequence) is + (delimited by the OS-dependent newline sequence) is delivered in a single message. The message data format is {Flag, Line}, where Flag is eol or noeol, and Line is the - data delivered (without the new line sequence).

+ data delivered (without the newline sequence).

L specifies the maximum line length in bytes. Lines longer than this are delivered in more than one message, with Flag set to noeol for all but the last message. If end of file is encountered - anywhere else than immediately following a new line + anywhere else than immediately following a newline sequence, the last line is also delivered with Flag set to noeol. Otherwise lines are delivered with Flag set to eol.

@@ -3455,14 +3510,14 @@ os_prompt% {cd, Dir}

Only valid for {spawn, Command} and - {spawn_executable, FileName}. + {spawn_executable, FileName}. The external program starts using Dir as its working directory. Dir must be a string.

{env, Env} -

Only valid for {spawn, Command} and - {spawn_executable, FileName}. +

Only valid for {spawn, Command}, and + {spawn_executable, FileName}. The environment of the started process is extended using the environment specifications in Env.

Env is to be a list of tuples @@ -3473,56 +3528,58 @@ os_prompt% port process. Both Name and Val must be strings. The one exception is Val being the atom - false (in analogy with os:getenv/1), which - removes the environment variable.

-
- {args, [ string() | binary() ]} - -

Only valid for {spawn_executable, FileName} - 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, a similar behavior is mimicked.

-

The arguments are not expanded by the shell before - being supplied to the executable. Most notably this - means that file wild card expansion does not happen. - To expand wild cards for the arguments, use - filelib:wildcard/1. - Notice that even if - the program is a Unix shell script, meaning that the - shell ultimately is invoked, wild card expansion - does not happen, and the script is provided with the - untouched arguments. On Windows, wild card expansion - is always up to the program itself, therefore this is - not an issue issue.

-

The executable name (also known as argv[0]) - is not to be given in this list. The proper executable name - is automatically used as argv[0], where applicable.

-

If you explicitly want to set the - program name in the argument vector, option arg0 - can be used.

-
- {arg0, string() | binary()} - -

Only valid for {spawn_executable, FileName} - and explicitly specifies the program name argument when - running an executable. This can in some circumstances, - on some OSs, be desirable. How the program - responds to this is highly system-dependent and no specific - effect is guaranteed.

-
+ false (in analogy with + os:getenv/1, + which removes the environment variable.

+
+ {args, [ string() | binary() ]} + +

Only valid for {spawn_executable, FileName} + and specifies arguments to the executable. Each argument + is specified as a separate string and (on Unix) eventually + ends up as one element each in the argument vector. On + other platforms, a similar behavior is mimicked.

+

The arguments are not expanded by the shell before + they are supplied to the executable. Most notably this + means that file wildcard expansion does not occur. + To expand wildcards for the arguments, use + + filelib:wildcard/1 in STDLIB. + Notice that even if + the program is a Unix shell script, meaning that the + shell ultimately is invoked, wildcard expansion + does not occur, and the script is provided with the + untouched arguments. On Windows, wildcard expansion + is always up to the program itself, therefore this is + not an issue.

+

The executable name (also known as argv[0]) + is not to be specified in this list. The proper executable name + is automatically used as argv[0], where applicable.

+

If you explicitly want to set the + program name in the argument vector, option arg0 + can be used.

+
+ {arg0, string() | binary()} + +

Only valid for {spawn_executable, FileName} + and explicitly specifies the program name argument when + running an executable. This can in some circumstances, + on some OSs, be desirable. How the program + responds to this is highly system-dependent and no specific + effect is guaranteed.

+
exit_status

Only valid for {spawn, Command}, where Command refers to an external program, and - for {spawn_executable, FileName}.

+ for {spawn_executable, FileName}.

When the external process connected to the port exits, a message of the form {Port,{exit_status,Status}} is sent to the connected process, where Status is the exit status of the external process. If the program aborts on Unix, the same convention is used as the shells do (that is, 128+signal).

-

If option eof is also given, the messages eof +

If option eof is specified also, the messages eof and exit_status appear in an unspecified order.

If the port program closes its stdout without exiting, option exit_status does not work.

@@ -3530,7 +3587,7 @@ os_prompt% use_stdio

Only valid for {spawn, Command} and - {spawn_executable, FileName}. It + {spawn_executable, FileName}. It allows the standard input and output (file descriptors 0 and 1) of the spawned (Unix) process for communication with Erlang.

@@ -3550,14 +3607,14 @@ os_prompt% overlapped_io

Affects ports to external programs on Windows only. The - standard input and standard output handles of the port program - are, if this option is supplied, opened with flag - FILE_FLAG_OVERLAPPED, so that the port program can - (and must) do - overlapped I/O on its standard handles. This is not normally - the case for simple port programs, but an option of value for the - experienced Windows programmer. On all other platforms, this - option is silently discarded.

+ standard input and standard output handles of the port program + are, if this option is supplied, opened with flag + FILE_FLAG_OVERLAPPED, so that the port program can + (and must) do + overlapped I/O on its standard handles. This is not normally + the case for simple port programs, but an option of value for the + experienced Windows programmer. On all other platforms, this + option is silently discarded.

in @@ -3582,27 +3639,28 @@ os_prompt% hide

When running on Windows, suppresses creation of a new - console window when spawning the port program. - (This option has no effect on other platforms.)

+ console window when spawning the port program. + (This option has no effect on other platforms.)

{parallelism, Boolean} - +

Sets scheduler hint for port parallelism. If set to - true, the Virtual Machine schedules port tasks; - when doing so, it improves parallelism in the system. If set - to false, the Virtual Machine tries to - perform port tasks immediately, improving latency at the - expense of parallelism. The default can be set at system startup - by passing command-line argument - +spp to erl(1).

+ true, the virtual machine schedules port tasks; + when doing so, it improves parallelism in the system. If set + to false, the virtual machine tries to + perform port tasks immediately, improving latency at the + expense of parallelism. The default can be set at system startup + by passing command-line argument + +spp to + erl(1).

Default is stream for all port types and use_stdio for spawned ports.

-

Failure: If the port cannot be opened, the exit reason is - badarg, system_limit, or the POSIX error code that - most closely describes the error, or einval if no POSIX +

Failure: if the port cannot be opened, the exit reason is + badarg, system_limit, or the POSIX error code that + most closely describes the error, or einval if no POSIX code is appropriate:

badarg @@ -3628,11 +3686,11 @@ os_prompt% Full file table (for the entire OS). eacces - Command given in {spawn_executable, Command} + Command specified in {spawn_executable, Command} does not point out an executable file. enoent - FileName given in + FileName specified in {spawn_executable, FileName} does not point out an existing file. @@ -3642,13 +3700,12 @@ os_prompt% errors arising when sending messages to it are reported to the owning process using signals of the form {'EXIT', Port, PosixCode}. For the possible values of - PosixCode, see the - file(3) - manual page in Kernel.

-

The maximum number of ports that can be open at the same + PosixCode, see + kernel:file(3).

+

The maximum number of ports that can be open at the same time can be configured by passing command-line flag - +Q to - erl(1).

+ +Q to + erl(1).

@@ -3663,7 +3720,7 @@ os_prompt% The function returns a hash value for Term within the range 1..Range. The maximum value for - Range is 2^32.

+ Range is 2^32.

This BIF can be used instead of the old deprecated BIF erlang:hash/2, as it calculates better hashes for all data types, but consider using phash2/1,2 instead.

@@ -3681,9 +3738,9 @@ os_prompt% the same Erlang term regardless of machine architecture and ERTS version (the BIF was introduced in ERTS 5.2). The function returns a hash value for - Term within the range - 0..Range-1. The maximum value for - Range is 2^32. When without argument + Term within the range + 0..Range-1. The maximum value for + Range is 2^32. When without argument Range, a value in the range 0..2^27-1 is returned.

This BIF is always to be used for hashing terms. It @@ -3703,14 +3760,14 @@ os_prompt% representation of Pid.

This BIF is intended for debugging and is not to be used - in application programs.

+ in application programs.

- Performs a synchronous call to a port with term data. + Perform a synchronous call to a port with term data.

Performs a synchronous call to a port. The meaning of Operation and Data @@ -3728,87 +3785,84 @@ os_prompt% badarg - If Port is not an identifier of an open port, - or the registered name of an open port. If the calling - process was previously linked to the closed port, - identified by Port, the exit signal - from the port is guaranteed to be delivered before this - badarg exception occurs. - + If Port is not an identifier of an open port, + or the registered name of an open port. If the calling + process was previously linked to the closed port, + identified by Port, the exit signal + from the port is guaranteed to be delivered before this + badarg exception occurs. + badarg - - If Operation does not fit in a 32-bit integer. - + + If Operation does not fit in a 32-bit integer. + badarg - - If the port driver does not support synchronous control - operations. - + + If the port driver does not support synchronous control operations. + badarg - - If the port driver so decides for any reason (probably - something wrong with Operation - or Data). - - + + If the port driver so decides for any reason (probably + something wrong with Operation + or Data). + + - Closes an open port. - -

Closes an open port. Roughly the same as - Port ! {self(), close} except for the error behavior - (see the following), being synchronous, and that the port does - not reply with {Port, closed}. Any process can - close a port with port_close/1, not only the port owner - (the connected process). If the calling process is linked to + Close an open port. + +

Closes an open port. Roughly the same as Port ! + {self(), close} except for the error behavior + (see below), being synchronous, and that the port does + not reply with {Port, closed}. Any process can + close a port with port_close/1, not only the port owner + (the connected process). If the calling process is linked to the port identified by Port, the exit - signal from the port is guaranteed to be delivered before - port_close/1 returns.

+ signal from the port is guaranteed to be delivered before + port_close/1 returns.

For comparison: Port ! {self(), close} - only fails with badarg if Port does - not refer to a port or a process. If Port - is a closed port, nothing happens. If Port + only fails with badarg if Port does + not refer to a port or a process. If Port + is a closed port, nothing happens. If Port is an open port and the calling process is the port owner, - the port replies with {Port, closed} when all buffers - have been flushed and the port really closes. If the calling - process is not the port owner, the port owner fails - with badsig.

+ the port replies with {Port, closed} when all buffers + have been flushed and the port really closes. If the calling + process is not the port owner, the port owner fails + with badsig.

Notice that any process can close a port using Port ! {PortOwner, close} as if it itself was the port owner, but the reply always goes to the port owner.

-

As from OTP R16, Port ! {PortOwner, close} is truly - asynchronous. Notice that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. port_close/1 is - however still fully synchronous. This because of its error - behavior.

-

Failure: badarg if Port is not an identifier - of an open port, or the registered name of an open port. - If the calling process was previously linked to the closed - port, identified by Port, the exit - signal from the port is guaranteed to be delivered before - this badarg exception occurs.

+

As from Erlang/OTP R16, + Port ! {PortOwner, close} is truly + asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. port_close/1 is + however still fully synchronous because of its error behavior.

+

Failure: badarg if Port is not an + identifier of an open port, or the registered name of an open port. + If the calling process was previously linked to the closed + port, identified by Port, the exit + signal from the port is guaranteed to be delivered before + this badarg exception occurs.

- Sends data to a port. + Send data to a port.

Sends data to a port. Same as - Port ! {PortOwner, {command, Data}} except - for the error - behavior and being synchronous (see the following). Any process - can send data to a port with port_command/2, not only the - port owner (the connected process).

-

For comparison: Port ! {PortOwner, {command, Data}} - only fails with badarg if Port - does not refer to a port or a process. If - Port is a closed port, the data message - disappears + Port ! {PortOwner, {command, Data}} except for + the error behavior and being synchronous (see below). Any process + can send data to a port with port_command/2, not only the + port owner (the connected process).

+

For comparison: Port ! {PortOwner, {command, + Data}} only fails with badarg if Port + does not refer to a port or a process. If Port is + a closed port, the data message disappears without a sound. If Port is open and the calling process is not the port owner, the port owner fails with badsig. The port owner fails with badsig @@ -3816,57 +3870,58 @@ os_prompt%

Notice that any process can send to a port using Port ! {PortOwner, {command, Data}} as if it itself was the port owner.

-

If the port is busy, the calling process is suspended - until the port is not busy any more.

-

As from OTP-R16, Port ! {PortOwner, {command, Data}} - is truly asynchronous. Notice that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. port_command/2 is - however still fully synchronous. This because of its error - behavior.

+

If the port is busy, the calling process is suspended + until the port is not busy any more.

+

As from Erlang/OTP R16, + Port ! {PortOwner, {command, Data}} + is truly asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. port_command/2 is + however still fully synchronous because of its error behavior.

Failures:

badarg - If Port is not an identifier of an open - port, or the registered name of an open port. If the - calling process was previously linked to the closed port, - identified by Port, the exit signal - from the port is guaranteed to be delivered before this - badarg exception occurs. - +

If Port is not an identifier of an open + port, or the registered name of an open port. If the + calling process was previously linked to the closed port, + identified by Port, the exit signal + from the port is guaranteed to be delivered before this + badarg exception occurs.

+ badarg - If Data is an invalid I/O list. - -
+

If Data is an invalid I/O list.

+ +
- Sends data to a port. + Send data to a port.

Sends data to a port. port_command(Port, Data, []) - equals port_command(Port, Data).

-

If the port command is aborted, false is returned, - otherwise true.

-

If the port is busy, the calling process is suspended - until the port is not busy any more.

-

The following Options are valid:

+ equals port_command(Port, Data).

+

If the port command is aborted, false is returned, + otherwise true.

+

If the port is busy, the calling process is suspended + until the port is not busy anymore.

+

Options:

force The calling process is not suspended if the port is - busy, instead the port command is forced through. The - call fails with a notsup exception if the - driver of the port does not support this. For more - information, see driver flag - . + busy, instead the port command is forced through. The + call fails with a notsup exception if the + driver of the port does not support this. For more + information, see driver flag + + ![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]. nosuspend The calling process is not suspended if the port is - busy, instead the port command is aborted and - false is returned. + busy, instead the port command is aborted and + false is returned. @@ -3876,34 +3931,34 @@ os_prompt% badarg - If Port is not an identifier of an open - port, or the registered name of an open port. If the - calling process was previously linked to the closed port, - identified by Port, the exit signal - from the port is guaranteed to be delivered before this - badarg exception occurs. - + If Port is not an identifier of an open + port, or the registered name of an open port. If the + calling process was previously linked to the closed port, + identified by Port, the exit signal + from the port is guaranteed to be delivered before this + badarg exception occurs. + badarg - If Data is an invalid I/O list. - + If Data is an invalid I/O list. + badarg - If OptionList is an invalid option list. - + If OptionList is an invalid option list. + notsup - If option force has been passed, but the - driver of the port does not allow forcing through - a busy port. - - + If option force has been passed, but the + driver of the port does not allow forcing through + a busy port. + +
- Sets the owner of a port. + Set the owner of a port.

Sets the port owner (the connected port) to Pid. Roughly the same as @@ -3911,14 +3966,14 @@ os_prompt% except for the following:

-

The error behavior differs, see the following.

+

The error behavior differs, see below.

The port does not reply with {Port,connected}.

-

port_connect/1 is synchronous, see the following.

+

port_connect/1 is synchronous, see below.

The new port owner gets linked to the port.

@@ -3930,7 +3985,7 @@ os_prompt% port_connect/2.

For comparison: Port ! {self(), {connect, Pid}} - only fails with badarg if Port + only fails with badarg if Port does not refer to a port or a process. If Port is a closed port, nothing happens. If Port @@ -3940,40 +3995,39 @@ os_prompt% the port, while the new is not. If Port is an open port and the calling process is not the port owner, the port owner fails with badsig. The port - owner fails with badsig also if Pid is not an - existing local process identifier.

+ owner fails with badsig also if Pid is not + an existing local process identifier.

Notice that any process can set the port owner using Port ! {PortOwner, {connect, Pid}} as if it itself was the port owner, but the reply always goes to the port owner.

-

As from OTP-R16, - Port ! {PortOwner, {connect, Pid}} is - truly asynchronous. Notice that this operation has always been - documented as an asynchronous operation, while the underlying - implementation has been synchronous. port_connect/2 is - however still fully synchronous. This because of its error - behavior.

+

As from Erlang/OTP R16, + Port ! {PortOwner, {connect, Pid}} + is truly asynchronous. Notice that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. port_connect/2 is + however still fully synchronous because of its error behavior.

Failures:

badarg - If Port is not an identifier of an open port, or - the registered name of an open port. If the calling - process was previously linked to the closed port, - identified by Port, the exit signal - from the port is guaranteed to be delivered before this - badarg exception occurs. - + If Port is not an identifier of an open port, + or the registered name of an open port. If the calling + process was previously linked to the closed port, + identified by Port, the exit signal + from the port is guaranteed to be delivered before this + badarg exception occurs. +
badarg - If process identified by Pid is not an existing - local process. - + If the process identified by Pid is not an existing + local process. +
- Performs a synchronous control operation on a port. + Perform a synchronous control operation on a port.

Performs a synchronous control operation on a port. The meaning of Operation and @@ -3987,25 +4041,24 @@ os_prompt% badarg - If Port is not an open port or the registered - name of an open port. - + If Port is not an open port or the registered + name of an open port. + badarg - If Operation cannot fit in a 32-bit integer. - + If Operation cannot fit in a 32-bit integer. + badarg - If the port driver does not support synchronous control - operations. - + If the port driver does not support synchronous control operations. + badarg - If the port driver so decides for any reason (probably + If the port driver so decides for any reason (probably something wrong with Operation or Data). - - + + @@ -4017,11 +4070,11 @@ os_prompt% Port, or undefined if the port is not open. The order of the tuples is undefined, and all the tuples are not mandatory. - If the port is closed and the calling process - was previously linked to the port, the exit signal from the - port is guaranteed to be delivered before port_info/1 - returns undefined.

-

The result contains information about the following + If the port is closed and the calling process + was previously linked to the port, the exit signal from the + port is guaranteed to be delivered before port_info/1 + returns undefined.

+

The result contains information about the following Items:

registered_name (if the port has a registered @@ -4034,9 +4087,9 @@ os_prompt% output

For more information about the different Items, see - port_info/2.

+ port_info/2.

Failure: badarg if Port is not a local port - identifier, or an atom.

+ identifier, or an atom.

@@ -4044,15 +4097,15 @@ os_prompt% Information about the connected process of a port. -

Pid is the process identifier of the process - connected to the port.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Pid is the process identifier of the process + connected to the port.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4060,15 +4113,15 @@ os_prompt% Information about the internal index of a port. -

Index is the internal index of the port. This - index can be used to separate ports.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Index is the internal index of the port. This + index can be used to separate ports.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4076,15 +4129,15 @@ os_prompt% Information about the input of a port. -

Bytes is the total number of bytes - read from the port.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Bytes is the total number of bytes + read from the port.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4092,15 +4145,15 @@ os_prompt% Information about the links of a port. -

Pids is a list of the process identifiers - of the processes that the port is linked to.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Pids is a list of the process identifiers + of the processes that the port is linked to.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4108,7 +4161,7 @@ os_prompt% Information about the locking of a port. -

Locking is one of the following:

+

Locking is one of the following:

false (emulator without SMP support) port_level (port-specific locking) @@ -4116,13 +4169,13 @@ os_prompt%

Notice that these results are highly implementation-specific and can change in a future release.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4130,17 +4183,17 @@ os_prompt% Information about the memory size of a port. -

Bytes is the total number of - bytes allocated for this port by the runtime system. The - port itself can have allocated memory that is not - included in Bytes.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Bytes is the total number of + bytes allocated for this port by the runtime system. The + port itself can have allocated memory that is not + included in Bytes.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4148,15 +4201,15 @@ os_prompt% Information about the monitors of a port. -

Monitors represent processes that this port - monitors.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Monitors represent processes monitored by + this port.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4180,15 +4233,15 @@ os_prompt% Information about the name of a port. -

Name is the command name set by - open_port/2.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Name is the command name set by + open_port/2.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4196,18 +4249,18 @@ os_prompt% Information about the OS pid of a port. -

OsPid is the process identifier (or equivalent) - of an OS process created with - open_port({spawn | spawn_executable, - Command}, Options). If the port is not the result of spawning - an OS process, the value is undefined.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

OsPid is the process identifier (or equivalent) + of an OS process created with + open_port({spawn | spawn_executable, + Command}, Options). If the port is not the result of + spawning an OS process, the value is undefined.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4215,18 +4268,18 @@ os_prompt% Information about the output of a port. -

Bytes is the total number of bytes written - to the port from Erlang processes using - port_command/2, - port_command/3, - or Port ! {Owner, {command, Data}.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Bytes is the total number of bytes written + to the port from Erlang processes using + port_command/2, + port_command/3, + or Port ! {Owner, {command, Data}.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4234,10 +4287,10 @@ os_prompt% Information about the parallelism hint of a port. -

Boolean corresponds to the port parallelism - hint being used by this port. For more information, see option - parallelism - of open_port/2.

+

Boolean corresponds to the port parallelism + hint used by this port. For more information, see option + parallelism + of open_port/2.

@@ -4245,16 +4298,16 @@ os_prompt% Information about the queue size of a port. -

Bytes is the total number - of bytes queued by the port using the ERTS driver queue - implementation.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

Bytes is the total number + of bytes queued by the port using the ERTS driver queue + implementation.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4262,15 +4315,16 @@ os_prompt% Information about the registered name of a port. -

RegisteredName is the registered name of - the port. If the port has no registered name, [] is returned.

-

If the port identified by Port is not open, - undefined is returned. If the port is closed and the - calling process was previously linked to the port, the exit - signal from the port is guaranteed to be delivered before - port_info/2 returns undefined.

+

RegisteredName is the registered name of + the port. If the port has no registered name, [] is + returned.

+

If the port identified by Port is not open, + undefined is returned. If the port is closed and the + calling process was previously linked to the port, the exit + signal from the port is guaranteed to be delivered before + port_info/2 returns undefined.

Failure: badarg if Port is not a local - port identifier, or an atom.

+ port identifier, or an atom.

@@ -4282,24 +4336,24 @@ os_prompt% representation of the port identifier Port.

This BIF is intended for debugging. It is not to be used - in application programs.

+ in application programs.

- Lists all existing ports. + List all existing ports. -

Returns a list of port identifiers corresponding to all the - ports existing on the local node.

-

Notice that an exiting port exists, but is not open.

+

Returns a list of port identifiers corresponding to all the + ports existing on the local node.

+

Notice that an exiting port exists, but is not open.

- Lists all pre-loaded modules. + List all preloaded modules.

Returns a list of Erlang modules that are preloaded in the system. As all loading of code is done through the file @@ -4310,12 +4364,13 @@ os_prompt% - Writes information about a local process on standard error. + Write information about a local process on standard error. +

Writes information about the local process Pid on standard error. The only allowed value for the atom - Type is backtrace, which shows the contents of - the call stack, including information about the call chain, with + Type is backtrace, 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.

@@ -4323,7 +4378,7 @@ os_prompt% - Sets process flag trap_exit for the calling process. + Set process flag trap_exit for the calling process.

When trap_exit is set to true, exit signals arriving to a process are converted to {'EXIT', From, Reason} @@ -4334,13 +4389,14 @@ os_prompt% linked processes. Application processes are normally not to trap exits.

Returns the old value of the flag.

-

See also exit/2.

+

See also exit/2.

- Sets process flag error_handler for the calling process. + Set process flag error_handler for the calling process. +

Used by a process to redefine the error handler for undefined function calls and undefined registered @@ -4348,13 +4404,14 @@ os_prompt% as code auto-loading depends on the correct operation of the error handling module.

Returns the old value of the flag.

+
- - Sets process flag min_heap_size for the calling process. + Set process flag min_heap_size for the calling process. +

Changes the minimum heap size for the calling process.

Returns the old value of the flag.

@@ -4363,90 +4420,79 @@ os_prompt% - Sets process flag min_bin_vheap_size for the calling process. + Set process flag min_bin_vheap_size for the calling process. +

Changes the minimum binary virtual heap size for the calling process.

Returns the old value of the flag.

+ - Sets process flag max_heap_size for the calling process. + Set process flag max_heap_size for the calling process. + -

- This flag sets the maximum heap size for the calling process. +

This flag sets the maximum heap size for the calling process. If MaxHeapSize is an integer, the system default values for kill and error_logger are used.

size -

- The maximum size in words of the process. If set to zero, the - heap size limit is disabled. Badarg will be thrown if the value is - smaller than - min_heap_size. - The size check is only done when a garbage collection is triggered. -

-

- size is the entire heap of the process when garbage collection - is triggered, this includes all generational heaps, the process stack, +

The maximum size in words of the process. If set to zero, the + heap size limit is disabled. badarg is be thrown if the + value is smaller than + min_heap_size. The size check is only done when + a garbage collection is triggered.

+

size is the entire heap of the process when garbage collection + is triggered. This includes all generational heaps, the process stack, any - messages that are considered to be part of the heap and any - extra memory that the garbage collector needs during collection. -

-

- size is the same as can be retrieved using + messages that are considered to be part of the heap, and any + extra memory that the garbage collector needs during collection.

+

size is the same as can be retrieved using erlang:process_info(Pid, total_heap_size), - or by adding heap_block_size, old_heap_block_size - and mbuf_size from - erlang:process_info(Pid, garbage_collection_info). -

+ or by adding heap_block_size, old_heap_block_size + and mbuf_size from + erlang:process_info(Pid, garbage_collection_info).

kill -

- When set to true the runtime system will send an +

When set to true, the runtime system sends an untrappable exit signal with reason kill to the process if the maximum heap size is reached. The garbage collection - that triggered the kill will not be completed, instead the - process will exit as soon as is possible. When set to false - no exit signal will be sent to the process, instead it will - continue executing. -

-

- If kill is not defined in the map + that triggered the kill is not completed, instead the + process exits as soon as possible. When set to false, + no exit signal is sent to the process, instead it continues + executing.

+

If kill is not defined in the map, the system default will be used. The default system default - is true. It can be changed by either the erl - +hmaxk option, - or - erlang:system_flag(max_heap_size, MaxHeapSize). -

+ is true. It can be changed by either option + +hmaxk in erl(1), + or + erlang:system_flag(max_heap_size, MaxHeapSize).

error_logger -

- When set to true the runtime system will send a - message to the current error_logger +

When set to true, the runtime system sends a + message to the current + error_logger containing details about the process when the maximum - heap size is reached. One error_logger report will - be sent each time the limit is reached. -

-

- If error_logger is not defined in the map the system - default will be used. The default system default is true. - It can be changed by either the erl +hmaxel - option, or - erlang:system_flag(max_heap_size, MaxHeapSize). -

+ heap size is reached. One error_logger report is sent + each time the limit is reached.

+

If error_logger is not defined in the map, the system + default is used. The default system default is true. + It can be changed by either the option + +hmaxel int erl(1), + or + erlang:system_flag(max_heap_size, MaxHeapSize).

-

- The heap size of a process is quite hard to predict, especially the +

The heap size of a process is quite hard to predict, especially the amount of memory that is used during the garbage collection. When contemplating using this option, it is recommended to first run it in production with kill set to false and inspect @@ -4456,62 +4502,57 @@ os_prompt%

+ - Set process flag message_queue_data for the calling process + Set process flag message_queue_data for the calling process. + -

This flag determines how messages in the message queue - are stored. When the flag is:

+

This flag determines how messages in the message queue + are stored, as follows:

off_heap - -

- All messages in the message queue will be stored - outside of the process heap. This implies that no - messages in the message queue will be part of a garbage - collection of the process. -

+ +

All messages in the message queue will be stored + outside of the process heap. This implies that no + messages in the message queue will be part of a garbage + collection of the process.

+
on_heap - -

- All messages in the message queue will eventually be - placed on heap. They may however temporarily be stored - off heap. This is how messages always have been stored - up until ERTS version 8.0. -

+ +

All messages in the message queue will eventually be + placed on heap. They can however temporarily be stored + off heap. This is how messages always have been stored + up until ERTS 8.0.

+
-

- The default message_queue_data process flag is determined - by the +hmqd - erl command line argument. -

-

- If the process potentially may get a hugh amount of messages, - you are recommended to set the flag to off_heap. This - since a garbage collection with lots of messages placed on - the heap may become extremly expensive and the process may - consume large amounts of memory. Performance of the - actual message passing is however generally better when not - using the off_heap flag. -

-

- When changing this flag messages will be moved. This work - has been initiated but not completed when this function - call returns. -

+

The default message_queue_data process flag is determined + by command-line argument + +hmqd in erl(1).

+

If the process potentially can get many messages, + you are advised to set the flag to off_heap. This + because a garbage collection with many messages placed on + the heap can become extremly expensive and the process can + consume large amounts of memory. Performance of the + actual message passing is however generally better when not + using flag off_heap.

+

When changing this flag messages will be moved. This work + has been initiated but not completed when this function + call returns.

Returns the old value of the flag.

+ - Sets process flag priority for the calling process. + Set process flag priority for the calling process.

Sets the process priority. Level is an atom. - There are four priority levels: low, + Four priority levels exist: low, normal, high, and max. Default is normal.

@@ -4525,23 +4566,23 @@ os_prompt% low are interleaved. Processes on priority low are selected for execution less frequently than processes on priority normal.

-

When there are runnable processes on priority high, +

When runnable processes on priority high exist, no processes on priority low or normal are - selected for execution. Notice however, that this does + selected for execution. Notice however that this does not mean that no processes on priority low - or normal can run when there are processes - running on priority high. On the runtime + or normal can run when processes + are running on priority high. On the runtime system with SMP support, more processes can be running - in parallel than processes on priority high, that is, + in parallel than processes on priority high. That is, a low and a high priority process can execute at the same time.

-

When there are runnable processes on priority max, +

When runnable processes on priority max exist, no processes on priority low, normal, or high are selected for execution. As with priority high, processes on lower priorities can execute in parallel with processes on priority max.

-

Scheduling is preemptive. Regardless of priority, a process - is preempted when it has consumed more than a certain number +

Scheduling is pre-emptive. Regardless of priority, a process + is pre-empted when it has consumed more than a certain number of reductions since the last time it was selected for execution.

@@ -4557,7 +4598,7 @@ os_prompt% take this into account and handle such scenarios by yourself.

Making calls from a high priority process into code - that you have no control over can cause the high + that you has no control over can cause the high priority process to wait for a process with lower priority. That is, effectively decreasing the priority of the high priority process during the call. Even if this @@ -4571,8 +4612,8 @@ os_prompt% especially priority high. A process on priority high is only to perform work for short periods. Busy looping for - long periods in a high priority process does - most likely cause problems, as important OTP servers + long periods in a high priority process causes + most likely problems, as important OTP servers run on priority normal.

Returns the old value of the flag.

@@ -4580,10 +4621,10 @@ os_prompt% - Sets process flag save_calls for the calling process. + Set process flag save_calls for the calling process.

N must be an integer in the interval 0..10000. - If N is greater than 0, call saving is made + If N > 0, call saving is made active for the process. This means that information about the N most recent global function calls, BIF calls, sends, and @@ -4594,12 +4635,12 @@ os_prompt% explicitly mentioned. Only a fixed amount of information is saved, as follows:

- A tuple {Module, Function, Arity} for - function calls - The atoms send, 'receive', and +

A tuple {Module, Function, Arity} for + function calls

+

The atoms send, 'receive', and timeout for sends and receives ('receive' when a message is received and timeout when a - receive times out) + receive times out)

If N = 0, call saving is disabled for the process, which is the @@ -4611,7 +4652,7 @@ os_prompt% - Sets process flag sensitive for the calling process. + Set process flag sensitive for the calling process.

Sets or clears flag sensitive for the current process. When a process has been marked as sensitive by calling @@ -4621,13 +4662,13 @@ os_prompt%

Features that are disabled include (but are not limited to) the following:

- Tracing: Trace flags can still be set for the process, +

Tracing. Trace flags can still be set for the process, but no trace messages of any kind are generated. (If flag sensitive is turned off, trace messages are again - generated if any trace flags are set.) - Sequential tracing: The sequential trace token is + generated if any trace flags are set.)

+

Sequential tracing. The sequential trace token is propagated as usual, but no sequential trace messages are - generated. + generated.

process_info/1,2 cannot be used to read out the message queue or the process dictionary (both are returned @@ -4637,19 +4678,19 @@ os_prompt% are omitted.

If {save_calls,N} has been set for the process, no function calls are saved to the call saving list. - (The call saving list is not cleared. Furthermore, send, receive, - and timeout events are still added to the list.)

+ (The call saving list is not cleared. Also, send, receive, + and time-out events are still added to the list.)

Returns the old value of the flag.

- Sets process flags for a process. + Set process flags for a process.

Sets certain flags for the process Pid, in the same manner as - process_flag/2. + process_flag/2. Returns the old value of the flag. The valid values for Flag are only a subset of those allowed in process_flag/2, namely save_calls.

@@ -4664,46 +4705,46 @@ os_prompt% - - + +

Returns a list containing InfoTuples with - miscellaneous information about the process identified by - Pid, or undefined if the process is not alive.

-

The order of the InfoTuples is undefined and - all InfoTuples are not mandatory. + miscellaneous information about the process identified by + Pid, or undefined if the process is not alive.

+

The order of the InfoTuples is undefined and + all InfoTuples are not mandatory. The InfoTuples - part of the result can be changed without prior notice.

-

The InfoTuples with the following items - are part of the result:

+ part of the result can be changed without prior notice.

+

The InfoTuples with the following items + are part of the result:

current_function initial_call status - message_queue_len + message_queue_len messages links - dictionary + dictionary trap_exit error_handler - priority + priority group_leader total_heap_size - heap_size + heap_size stack_size reductions - garbage_collection + garbage_collection

If the process identified by Pid has a registered name, - also an InfoTuple with item registered_name - appears.

-

For information about specific InfoTuples, see - process_info/2.

+ also an InfoTuple with item registered_name + is included.

+

For information about specific InfoTuples, see + process_info/2.

This BIF is intended for debugging only. For - all other purposes, use - process_info/2.

+ all other purposes, use + process_info/2.

Failure: badarg if Pid is not a local process.

@@ -4718,38 +4759,39 @@ os_prompt% - - + +

Returns information about the process identified by - Pid, as specified by - Item or ItemList. - Returns undefined if the process is not alive.

-

If the process is alive and a single Item - is given, the returned value is the corresponding - InfoTuple, unless Item =:= registered_name - and the process has no registered name. In this case, - [] is returned. This strange behavior is because of - historical reasons, and is kept for backward compatibility.

-

If ItemList is given, the result is - InfoTupleList. - The InfoTuples in - InfoTupleList appear with the corresponding - Items in the same order as the - Items appeared - in ItemList. Valid Items can - appear multiple times in ItemList.

-

If registered_name is part of ItemList - and the process has no name registered a - {registered_name, []}, InfoTuple - will appear in the resulting - InfoTupleList. This - behavior is different when a single - Item =:= registered_name is given, and when - process_info/1 is used.

-
-

The following InfoTuples with corresponding - Items are valid:

+ Pid, as specified by + Item or ItemList. + Returns undefined if the process is not alive.

+

If the process is alive and a single Item + is specified, the returned value is the corresponding + InfoTuple, unless Item =:= registered_name + and the process has no registered name. In this case, + [] is returned. This strange behavior is because of + historical reasons, and is kept for backward compatibility.

+

If ItemList is specified, the result is + InfoTupleList. + The InfoTuples in + InfoTupleList are included with the corresponding + Items in the same order as the + Items were included + in ItemList. Valid Items can + be included multiple times in ItemList.

+ +

If registered_name is part of ItemList + and the process has no name registered, a + {registered_name, []}, InfoTuple + will be included in the resulting + InfoTupleList. This + behavior is different when a single + Item =:= registered_name is specified, and when + process_info/1 is used.

+
+

Valid InfoTuples with corresponding + Items:

{backtrace, Bin} @@ -4762,15 +4804,15 @@ os_prompt% {binary, BinInfo}

BinInfo is a list containing miscellaneous - information about binaries currently being referred to by this + information about binaries currently referred to by this process. This InfoTuple can be changed or removed without prior notice.

{catchlevel, CatchLevel}

CatchLevel is the number of currently active - catches in this process. This InfoTuple can be - changed or removed without prior notice.

+ catches in this process. This InfoTuple can be + changed or removed without prior notice.

{current_function, {Module, Function, Arity}} @@ -4786,14 +4828,15 @@ os_prompt%

Module, Function, Arity is the current function call of the process. - Location is a list of two-tuples describing the - location in the source code.

+ Location is a list of two-tuples describing + the location in the source code.

{current_stacktrace, Stack}

Returns the current call stack back-trace (stacktrace) of the process. The stack has the same format as returned by - erlang:get_stacktrace/0.

+ + erlang:get_stacktrace/0.

{dictionary, Dictionary} @@ -4807,9 +4850,9 @@ os_prompt% {garbage_collection, GCInfo}

GCInfo is a list containing miscellaneous - information about garbage collection for this process. - The content of GCInfo can be changed without - prior notice.

+ information about garbage collection for this process. + The content of GCInfo can be changed without + prior notice.

@@ -4817,24 +4860,22 @@ os_prompt%

GCInfo is a list containing miscellaneous - detailed information about garbage collection for this process. - The content of GCInfo can be changed without - prior notice. - See gc_minor_start in - erlang:trace/3 for details about - what each item means. -

+ detailed information about garbage collection for this process. + The content of GCInfo can be changed without + prior notice. For details about the meaning of each item, see + gc_minor_start + in erlang:trace/3.

{group_leader, GroupLeader} -

GroupLeader is group leader for the I/O of - the process.

+

GroupLeader is the group leader for the I/O + of the process.

{heap_size, Size} -

Size is the size in words of the youngest heap - generation of the process. This generation includes - the process stack. This information is highly +

Size is the size in words of the youngest + heap generation of the process. This generation includes + the process stack. This information is highly implementation-dependent, and can change if the implementation changes.

@@ -4848,29 +4889,29 @@ os_prompt%
{links, PidsAndPorts} -

PidsAndPorts is a list of process identifiers - and port identifiers, with processes or ports to which the process - has a link.

+

PidsAndPorts is a list of process identifiers + and port identifiers, with processes or ports to which the process + has a link.

{last_calls, false|Calls}

The value is false if call saving is not active - for the process (see - process_flag/3). + for the process (see + process_flag/3). If call saving is active, a list is returned, in which the last element is the most recent called.

{memory, Size} -

Size is the size in bytes of the process. This - includes call stack, heap, and internal structures.

+

Size is the size in bytes of the process. + This includes call stack, heap, and internal structures.

{message_queue_len, MessageQueueLen}

MessageQueueLen is the number of messages - currently in the message queue of the process. This is - the length of the list MessageQueue returned as - the information item messages (see the following).

+ currently in the message queue of the process. This is the + length of the list MessageQueue returned as + the information item messages (see below).

{messages, MessageQueue} @@ -4913,36 +4954,37 @@ os_prompt% {message_queue_data, MQD} -

Returns the current state of the message_queue_data - process flag. MQD is either off_heap, - or on_heap. For more information, see the - documentation of - process_flag(message_queue_data, - MQD).

+

Returns the current state of process flag + message_queue_data. MQD is either + off_heap or on_heap. For more + information, see the documentation of + + process_flag(message_queue_data, MQD).

{priority, Level}

Level is the current priority level for - the process. For more information on priorities, see - process_flag(priority, - Level).

+ the process. For more information on priorities, see + + process_flag(priority, Level).

{reductions, Number} -

Number is the number of reductions executed by - the process.

+

Number is the number of reductions executed + by the process.

{registered_name, Atom} -

Atom is the registered name of the process. If - the process has no registered name, this tuple is not +

Atom is the registered process name. + If the process has no registered name, this tuple is not present in the list.

- {sequential_trace_token, [] | SequentialTraceToken} + {sequential_trace_token, [] | + SequentialTraceToken}

SequentialTraceToken is the sequential trace - token for the process. This InfoTuple can be - changed or removed without prior notice.

+ token for the process. This InfoTuple can be + changed or removed without prior notice.

{stack_size, Size} @@ -4951,9 +4993,9 @@ os_prompt% {status, Status} -

Status is the status of the process and is one - of the following:

- +

Status is the status of the process and is + one of the following:

+ exiting garbage_collecting waiting (for a message) @@ -4961,46 +5003,44 @@ os_prompt% runnable (ready to run, but another process is running) suspended (suspended on a "busy" port - or by the BIF erlang:suspend_process/[1,2]) + or by the BIF erlang:suspend_process/1,2)
{suspending, SuspendeeList}

SuspendeeList is a list of - {Suspendee, ActiveSuspendCount, - OutstandingSuspendCount} tuples. - Suspendee is the process identifier of a - process that has been, or is to be, - suspended by the process identified by Pid - through one of the following BIFs:

+ {Suspendee, ActiveSuspendCount, + OutstandingSuspendCount} tuples. + Suspendee is the process identifier of a + process that has been, or is to be, + suspended by the process identified by Pid + through the BIF + erlang:suspend_process/2 or + + erlang:suspend_process/1.

+

ActiveSuspendCount is the number of + times Suspendee has been suspended by + Pid. + OutstandingSuspendCount is the number of not + yet completed suspend requests sent by Pid, + that is:

- erlang:suspend_process/2 - - - erlang:suspend_process/1 - - -

ActiveSuspendCount is the number of - times Suspendee has been suspended by - Pid. - OutstandingSuspendCount is the number of not yet - completed suspend requests sent by Pid, that is:

- - If ActiveSuspendCount =/= 0, - Suspendee is - currently in the suspended state. +

If ActiveSuspendCount =/= 0, + Suspendee is + currently in the suspended state.

- If OutstandingSuspendCount =/= 0, option - asynchronous of erlang:suspend_process/2 - has been used and the suspendee has not yet been - suspended by Pid. + +

If OutstandingSuspendCount =/= 0, + option asynchronous of erlang:suspend_process/2 + has been used and the suspendee has not yet been + suspended by Pid.

-

Notice that ActiveSuspendCount and - OutstandingSuspendCount are not the - total suspend count on Suspendee, - only the parts contributed by Pid.

+

Notice that ActiveSuspendCount and + OutstandingSuspendCount are not the + total suspend count on Suspendee, + only the parts contributed by Pid.

@@ -5008,21 +5048,21 @@ os_prompt%

Size is the total size, in words, of all heap - fragments of the process. This includes the process stack and - any unreceived messages that are considered to be part of the - heap.

+ fragments of the process. This includes the process stack and + any unreceived messages that are considered to be part of the + heap.

{trace, InternalTraceFlags}

InternalTraceFlags is an integer - representing the internal trace flag for this process. - This InfoTuple - can be changed or removed without prior notice.

+ representing the internal trace flag for this process. + This InfoTuple + can be changed or removed without prior notice.

{trap_exit, Boolean}

Boolean is true if the process - is trapping exits, otherwise false.

+ is trapping exits, otherwise false.

Notice that not all implementations support all @@ -5030,9 +5070,9 @@ os_prompt%

Failures:

badarg - If Pid is not a local process. + If Pid is not a local process. badarg - If Item is an invalid item. + If Item is an invalid item.
@@ -5042,11 +5082,11 @@ os_prompt% All processes.

Returns a list of process identifiers corresponding to - all the processes currently existing on the local node.

-

Notice that an exiting process exists, but is not alive. - That is, is_process_alive/1 returns false - for an exiting process, but its process identifier is part - of the result returned from processes/0.

+ all the processes currently existing on the local node.

+

Notice that an exiting process exists, but is not alive. + That is, is_process_alive/1 returns false + for an exiting process, but its process identifier is part + of the result returned from processes/0.

Example:

 > processes().
@@ -5056,22 +5096,23 @@ os_prompt% 
- Removes old code for a module. + Remove old code for a module.

Removes old code for Module. Before this BIF is used, - erlang:check_process_code/2 is to be called to check + + check_process_code/2is to be called to check that no processes execute old code in the module.

This BIF is intended for the code server (see - code(3)) + kernel:code(3)) and is not to be used elsewhere.

-

As from ERTS 8.0 (OTP 19), any lingering processes - that still execute the old code will be killed by this function. - In earlier versions, such incorrect use could cause much - more fatal failures, like emulator crash.

+

As from ERTS 8.0 (Erlang/OTP 19), any lingering processes + that still execute the old code is killed by this function. + In earlier versions, such incorrect use could cause much + more fatal failures, like emulator crash.

Failure: badarg if there is no old code for Module.

@@ -5080,14 +5121,13 @@ os_prompt% - Adds a new value to the process dictionary. + Add a new value to the process dictionary.

Adds a new Key to the process dictionary, associated with the value Val, and returns undefined. If Key exists, the old value is deleted and replaced by Val, and - the function returns the old value.

-

Example:

+ the function returns the old value. Example:

 > X = put(name, walrus), Y = put(name, carpenter),
 Z = get(name),
@@ -5103,17 +5143,18 @@ os_prompt% 
- Stops execution with an exception of given class, reason, and call stack backtrace. + Stop execution with an exception of specified class, reason, + and call stack backtrace.

Stops the execution of the calling process with an - exception of given class, reason, and call stack backtrace + exception of the specified class, reason, and call stack backtrace (stacktrace).

Class is error, exit, or throw. So, if it were not for the stacktrace, erlang:raise(Class, Reason, - Stacktrace) is - equivalent to erlang:Class(Reason).

+ Stacktrace) is equivalent to + erlang:Class(Reason).

Reason is any term. Stacktrace is a list as returned from get_stacktrace(), that is, a list of @@ -5123,12 +5164,12 @@ os_prompt% argument list. The stacktrace can also contain {Fun, Args, Location} tuples, where Fun is a local fun and Args is an argument list.

-

Element Location at the end is optional. - Omitting it is equivalent to specifying an empty list.

+

Element Location at the end is optional. + Omitting it is equivalent to specifying an empty list.

The stacktrace is used as the exception stacktrace for the calling process; it is truncated to the current maximum stacktrace depth.

-

Since evaluating this function causes the process to +

As evaluating this function causes the process to terminate, it has no return value unless the arguments are invalid, in which case the function returns the error reason badarg. If you want to be @@ -5141,77 +5182,67 @@ os_prompt% - Reads the state of a timer. + Read the state of a timer. -

Read the state of a timer. The same as calling - erlang:read_timer(TimerRef, - []).

+

Reads the state of a timer. The same as calling + erlang:read_timer(TimerRef, + []).

+ - Reads the state of a timer. - -

- Read the state of a timer that has been created by either - erlang:start_timer(), - or erlang:send_after(). - TimerRef identifies the timer, and - was returned by the BIF that created the timer. -

-

Available Options:

+ Read the state of a timer. + +

Reads the state of a timer that has been created by either + erlang:start_timer + or erlang:send_after. + TimerRef identifies the timer, and + was returned by the BIF that created the timer.

+

Options:

- {async, Async} - -

- Asynchronous request for state information. Async - defaults to false which will cause the operation - to be performed synchronously. In this case, the Result - is returned by erlang:read_timer(). When - Async is true, erlang:read_timer() - sends an asynchronous request for the state information - to the timer service that manages the timer, and then returns - ok. A message on the format {read_timer, - TimerRef, Result} is - sent to the caller of erlang:read_timer() when the - operation has been processed. -

-
+ {async, Async} + +

Asynchronous request for state information. Async + defaults to false, which causes the operation + to be performed synchronously. In this case, the Result + is returned by erlang:read_timer. When + Async is true, erlang:read_timer + sends an asynchronous request for the state information + to the timer service that manages the timer, and then returns + ok. A message on the format {read_timer, + TimerRef, Result} is + sent to the caller of erlang:read_timer when the + operation has been processed.

+
-

- More Options may be added in the future. -

-

- If Result is an integer, it represents the - time in milli-seconds left until the timer expires.

-

- If Result is false, a - timer corresponding to TimerRef could not - be found. This can be because the timer had expired, - it had been canceled, or because TimerRef - never has corresponded to a timer. Even if the timer has expired, - it does not tell you whether or not the timeout message has - arrived at its destination yet. -

- -

- The timer service that manages the timer may be co-located - with another scheduler than the scheduler that the calling - process is executing on. If this is the case, communication - with the timer service takes much longer time than if it - is located locally. If the calling process is in critical - path, and can do other things while waiting for the result - of this operation, you want to use option {async, true}. - If using option {async, false}, the calling - process will be blocked until the operation has been - performed. -

-
+

More Options can be added in the future.

+

If Result is an integer, it represents the + time in milliseconds left until the timer expires.

+

If Result is false, a + timer corresponding to TimerRef could not + be found. This because the timer had expired, + or been canceled, or because TimerRef + never has corresponded to a timer. Even if the timer has expired, + it does not tell you whether or not the time-out message has + arrived at its destination yet.

+ +

The timer service that manages the timer can be co-located + with another scheduler than the scheduler that the calling + process is executing on. If so, communication + with the timer service takes much longer time than if it + is located locally. If the calling process is in a critical + path, and can do other things while waiting for the result + of this operation, you want to use option {async, true}. + If using option {async, false}, the calling + process is blocked until the operation has been performed.

+

See also erlang:send_after/4, - erlang:start_timer/4, - and - erlang:cancel_timer/2.

+ + erlang:start_timer/4, and + + erlang:cancel_timer/2.

@@ -5223,21 +5254,20 @@ os_prompt% representation of Ref.

This BIF is intended for debugging and is not to be used - in application programs.

+ in application programs.

- Registers a name for a pid (or port). + Register a name for a pid (or port).

Associates the name RegName with a process identifier (pid) or a port identifier. RegName, which must be an atom, can be used instead of the pid or port identifier in send operator - (RegName ! Message).

-

Example:

+ (RegName ! Message). Example:

 > register(db, Pid).
 true
@@ -5263,7 +5293,7 @@ true All registered names.

Returns a list of names that have been registered using - register/2, for + register/2, for example:

 > registered().
@@ -5273,20 +5303,21 @@ true
- Resumes a suspended process. + Resume a suspended process.

Decreases the suspend count on the process identified by - Suspendee. Suspendee - is previously to have been suspended through - erlang:suspend_process/2 - or - erlang:suspend_process/1 - by the process calling - erlang:resume_process(Suspendee). When the - suspend count on Suspendee reaches zero, - Suspendee is resumed, that is, its state - is changed from suspended into the state it had before it was - suspended.

+ Suspendee. Suspendee + is previously to have been suspended through + + erlang:suspend_process/2 or + + erlang:suspend_process/1 + by the process calling + erlang:resume_process(Suspendee). When the + suspend count on Suspendee reaches zero, + Suspendee is resumed, that is, its state + is changed from suspended into the state it had before it was + suspended.

This BIF is intended for debugging only.

@@ -5294,29 +5325,29 @@ true badarg - If Suspendee is not a process identifier. - + If Suspendee is not a process identifier. + badarg - If the process calling erlang:resume_process/1 had - not previously increased the suspend count on the process - identified by Suspendee. - + If the process calling erlang:resume_process/1 had + not previously increased the suspend count on the process + identified by Suspendee. + badarg - If the process identified by Suspendee - is not alive. - + If the process identified by Suspendee + is not alive. +
- Returns an integer by rounding a number. + Return an integer by rounding a number.

Returns an integer by rounding Number, - for example:

+ for example:

 round(5.5).
 6
@@ -5326,7 +5357,7 @@ true - Returns pid of the calling process. + Return pid of the calling process.

Returns the process identifier of the calling process, for example:

@@ -5339,7 +5370,7 @@ true - Sends a message. + Send a message.

Sends a message and returns Msg. This @@ -5353,27 +5384,27 @@ true - Sends a message conditionally. + Send a message conditionally.

Either sends a message and returns ok, or does not send - the message but returns something else (see the following). + the message but returns something else (see below). Otherwise the same as - erlang:send/2. + erlang:send/2. For more detailed explanation and warnings, see - erlang:send_nosuspend/2,3.

-

The options are as follows:

+ + erlang:send_nosuspend/2,3.

+

Options:

nosuspend - -

If the sender would have to be suspended to do the send, - nosuspend is returned instead.

+ If the sender would have to be suspended to do the send, + nosuspend is returned instead. noconnect -

If the destination node would have to be auto-connected - to do the send, noconnect is returned - instead.

+ If the destination node would have to be auto-connected + to do the send, noconnect is returned + instead.
@@ -5385,35 +5416,36 @@ true - Starts a timer. + Start a timer.

Starts a timer. The same as calling - erlang:send_after(Time, - Dest, Msg, []).

+ + erlang:send_after(Time, Dest, + Msg, []).

+ - Start a timer + Start a timer. -

- Starts a timer. When the timer expires, the message +

Starts a timer. When the timer expires, the message Msg is sent to the process - identified by Dest. Apart from - the format of the timeout message, - erlang:send_after/4 works exactly as - erlang:start_timer/4.

+ identified by Dest. Apart from + the format of the time-out message, this function works exactly as + + erlang:start_timer/4.

- Tries to send a message without ever blocking. + Try to send a message without ever blocking.

The same as - erlang:send(Dest, - Msg, [nosuspend]), + erlang:send(Dest, + Msg, [nosuspend]), but returns true if the message was sent and false if the message was not sent because the sender would have had to be suspended.

@@ -5439,12 +5471,12 @@ true contradictory to the Erlang programming model. The message is not sent if this function returns false.

In many systems, transient states of - overloaded queues are normal. The fact that this function + overloaded queues are normal. Although this function returns false does not mean that the other node is guaranteed to be non-responsive, it could be a temporary overload. Also, a return value of true does only mean that the message can be sent on the (TCP) channel - without blocking, the message is not guaranteed to + without blocking; the message is not guaranteed to arrive at the remote node. For a disconnected non-responsive node, the return value is true (mimics the behavior of operator !). The expected @@ -5458,15 +5490,16 @@ true - Tries to send a message without ever blocking. + Try to send a message without ever blocking.

The same as - erlang:send(Dest, - Msg, [nosuspend | Options]), + erlang:send(Dest, + Msg, [nosuspend | Options]), but with a Boolean return value.

This function behaves like - erlang:send_nosuspend/2, + + erlang:send_nosuspend/2, but takes a third parameter, a list of options. The only option is noconnect, which makes the function return false if @@ -5490,14 +5523,15 @@ true - Sets the magic cookie of a node. + Set the magic cookie of a node.

Sets the magic cookie of Node to the atom Cookie. If Node is the local node, the function also sets the cookie of all other unknown nodes to - Cookie (see Section - Distributed Erlang + Cookie (see section + + Distributed Erlang in the Erlang Reference Manual in System Documentation).

Failure: function_clause if the local node is not alive.

@@ -5506,12 +5540,12 @@ true - Sets the Nth element of a tuple. + Set the Nth element of a tuple. 1..tuple_size(Tuple1

Returns a tuple that is a copy of argument Tuple1 - with the element given by integer argument + with the element specified by integer argument Index (the first element is the element with index 1) replaced by argument Value, for example:

@@ -5526,52 +5560,52 @@ true Size of a tuple or binary.

Returns the number of elements in a tuple or the number of - bytes in a binary or bitstring, for example:

+ bytes in a binary or bitstring, for example:

 > size({morni, mulle, bwange}).
 3
 > size(<<11, 22, 33>>).
-3
-
-

For bitstrings the number of whole bytes is returned. That is, if the number of bits +3 +

For bitstrings, the number of whole bytes is returned. + That is, if the number of bits in the bitstring is not divisible by 8, the resulting number of bytes is rounded down.

Allowed in guard tests.

See also tuple_size/1, - byte_size/1 - and + byte_size/1, and bit_size/1.

- Creates a new process with a fun as entry point. + Create a new process with a fun as entry point.

Returns the process identifier of a new process started by the application of Fun to the empty list []. Otherwise - works like spawn/3.

+ works like spawn/3.

- Creates a new process with a fun as entry point on a given node. + Create a new process with a fun as entry point on a specified + node.

Returns the process identifier of a new process started by the application of Fun to the empty list [] on Node. If Node does not exist, a useless pid is returned. Otherwise works like - spawn/3.

+ spawn/3.

- Creates a new process with a function as entry point. + Create a new process with a function as entry point.

Returns the process identifier of a new process started by the application of Module:Function @@ -5583,7 +5617,7 @@ true does not exist (where Arity is the length of Args). The error handler can be redefined (see - process_flag/2). + process_flag/2). If error_handler is undefined, or the user has redefined the default error_handler and its replacement is undefined, a failure with reason undef occurs.

@@ -5596,7 +5630,8 @@ true - Creates a new process with a function as entry point on a given node. + Create a new process with a function as entry point on a + specified node.

Returns the process identifier (pid) of a new process started by the application @@ -5604,26 +5639,28 @@ true to Args on Node. If Node does not exist, a useless pid is returned. Otherwise works like - spawn/3.

+ spawn/3.

- Creates and links to a new process with a fun as entry point. + Create and link to a new process with a fun as entry point. +

Returns the process identifier of a new process started by the application of Fun to the empty list []. A link is created between the calling process and the new process, atomically. Otherwise works like - spawn/3.

+ spawn/3.

- Creates and links to a new process with a fun as entry point on a specified node. + Create and link to a new process with a fun as entry point on + a specified node.

Returns the process identifier (pid) of a new process started by the application of Fun to the empty @@ -5632,26 +5669,29 @@ true atomically. If Node does not exist, a useless pid is returned and an exit signal with reason noconnection is sent to the calling - process. Otherwise works like spawn/3.

+ process. Otherwise works like + spawn/3.

- Creates and links to a new process with a function as entry point. + Create and link to a new process with a function as entry point. +

Returns the process identifier of a new process started by the application of Module:Function to Args. A link is created between the calling process and the new process, atomically. Otherwise works like - spawn/3.

+ spawn/3.

- Creates and links to a new process with a function as entry point on a given node. + Create and link to a new process with a function as entry point + on a specified node.

Returns the process identifier (pid) of a new process started by the application @@ -5661,109 +5701,113 @@ true process, atomically. If Node does not exist, a useless pid is returned and an exit signal with reason noconnection is sent to the calling - process. Otherwise works like spawn/3.

+ process. Otherwise works like + spawn/3.

- Creates and monitors a new process with a fun as entry point. + Create and monitor a new process with a fun as entry point. +

Returns the process identifier of a new process, started by the application of Fun to the empty list [], and a reference for a monitor created to the new process. Otherwise works like - spawn/3.

+ spawn/3.

- Creates and monitors a new process with a function as entry point. + Create and monitor a new process with a function as entry point. +

A new process is started by the application of Module:Function to Args. The process is monitored at the same time. Returns the process identifier and a reference for the monitor. Otherwise works like - spawn/3.

+ spawn/3.

- Creates a new process with a fun as entry point. + Create a new process with a fun as entry point. - - - + + +

Returns the process identifier (pid) of a new process started by the application of Fun to the empty list []. Otherwise works like - spawn_opt/4.

-

If option monitor is given, the newly created + spawn_opt/4.

+

If option monitor is specified, the newly created process is monitored, and both the pid and reference for - the monitor is returned.

+ the monitor are returned.

- Creates a new process with a fun as entry point on a given node. + Create a new process with a fun as entry point on a specified + node. - - - + + +

Returns the process identifier (pid) of a new process started by the application of Fun to the empty list [] on Node. If Node does not exist, a useless pid is returned. Otherwise works like - spawn_opt/4.

+ spawn_opt/4.

- Creates a new process with a function as entry point. + Create a new process with a function as entry point. - - - + + +

Works as - spawn/3, except that an - extra option list is given when creating the process.

-

If option monitor is given, the newly created + spawn/3, except that an + extra option list is specified when creating the process.

+

If option monitor is specified, the newly created process is monitored, and both the pid and reference for - the monitor is returned.

-

The options are as follows:

+ the monitor are returned.

+

Options:

link

Sets a link to the parent process (like - spawn_link/3 does).

+ spawn_link/3 + does).

monitor

Monitors the new process (like - monitor/2 does).

+ monitor/2 does).

{priority, Level

Sets the priority of the new process. Equivalent to - executing - process_flag(priority, - Level) + executing + process_flag(priority, Level) in the start function of the new process, except that the priority is set before the process is selected for execution for the first time. For more information on priorities, see - process_flag(priority, - Level).

+ + process_flag(priority, Level).

{fullsweep_after, Number} @@ -5786,21 +5830,22 @@ true

A few cases when it can be useful to change fullsweep_after:

- If binaries that are no longer used are to be +

If binaries that are no longer used are to be thrown away as soon as possible. (Set - Number to zero.) + Number to zero.)

- A process that mostly have short-lived data is +

A process that mostly have short-lived data is fullsweeped seldom or never, that is, the old heap contains mostly garbage. To ensure a fullsweep occasionally, set Number to a - suitable value, such as 10 or 20. + suitable value, such as 10 or 20.

In embedded systems with a limited amount of RAM and no virtual memory, you might want to preserve memory by setting Number to zero. (The value can be set globally, see - erlang:system_flag/2.) + + erlang:system_flag/2.)
@@ -5825,7 +5870,7 @@ true option unless you know that there is problem with execution times or memory consumption, and ensure that the option improves matters.

-

Gives a minimum binary virtual heap size, in words. +

Gives a minimum binary virtual heap size, in words. Setting this value higher than the system default can speed up some processes because less garbage collection is done. @@ -5837,24 +5882,25 @@ true {max_heap_size, Size}

Sets the max_heap_size process flag. The default - max_heap_size is determined by the - +hmax erl - command line argument. For more information, see the - documentation of - process_flag(max_heap_size, - Size).

+ max_heap_size is determined by command-line argument + +hmax + in erl/1. For more information, see the + documentation of + process_flag(max_heap_size, Size). +

{message_queue_data, MQD}

Sets the state of the message_queue_data process - flag. MQD should be either off_heap, - or on_heap. The default - message_queue_data process flag is determined by the - +hmqd erl - command line argument. For more information, see the - documentation of - process_flag(message_queue_data, - MQD).

+ flag. MQD is to be either off_heap + or on_heap. The default + message_queue_data process flag is determined by + command-line argument + +hmqd in erl/1. + For more information, see the documentation of + + process_flag(message_queue_data, + MQD).

@@ -5862,11 +5908,12 @@ true - Creates a new process with a function as entry point on a given node. + Create a new process with a function as entry point on a + specified node. - - - + + +

Returns the process identifier (pid) of a new process started by the application @@ -5874,23 +5921,24 @@ true Args on Node. If Node does not exist, a useless pid is returned. Otherwise works like - spawn_opt/4.

-

Option monitor is not supported by - spawn_opt/5.

+ spawn_opt/4.

+ +

Option monitor is not supported by + spawn_opt/5.

+
- Splits a binary into two. + Split a binary into two. 0..byte_size(Bin)

Returns a tuple containing the binaries that are the result of splitting Bin into two parts at position Pos. This is not a destructive operation. After the operation, - there are three binaries altogether.

-

Example:

+ there are three binaries altogether. Example:

 > B = list_to_binary("0123456789").
 <<"0123456789">>
@@ -5907,79 +5955,68 @@ true
- Starts a timer. + Start a timer.

Starts a timer. The same as calling - erlang:start_timer(Time, - Dest, Msg, []).

+ + erlang:start_timer(Time, + Dest, Msg, []).

- Starts a timer. + Start a timer. -

- Starts a timer. When the timer expires, the message +

Starts a timer. When the timer expires, the message {timeout, TimerRef, Msg} - is sent to the process identified by - Dest. -

-

Available Options:

+ is sent to the process identified by Dest.

+

Options:

{abs, false} -

- This is the default. It means the - Time value is interpreted - as a time in milli-seconds relative current - Erlang - monotonic time. -

-
+

This is the default. It means the + Time value is interpreted + as a time in milliseconds relative current + Erlang + monotonic time.

+ {abs, true} -

- Absolute Time value. The - Time value is interpreted as an - absolute Erlang monotonic time in milli-seconds. -

-
+

Absolute Time value. The + Time value is interpreted as an + absolute Erlang monotonic time in milliseconds.

+
-

- More Options may be added in the future. -

-

- The absolute point in time, the timer is set to expire on, - has to be in the interval - [erlang:system_info(start_time), - erlang:system_info(end_time)]. - Further, if a relative time is specified, the Time value - is not allowed to be negative. -

-

- If Dest is a pid(), it must - be a pid() of a process created on the current - runtime system instance. This process may or may not - have terminated. If Dest is an - atom(), it is interpreted as the name of a - locally registered process. The process referred to by the - name is looked up at the time of timer expiration. No error - is given if the name does not refer to a process. -

-

- If Dest is a pid(), the timer is - automatically canceled if the process referred to by the - pid() is not alive, or if the process exits. This - feature was introduced in ERTS version 5.4.11. Notice that - timers are not automatically canceled when - Dest is an atom(). -

+

More Options can be added in the future.

+

The absolute point in time, the timer is set to expire on, + must be in the interval + [ + erlang:system_info(start_time), + + erlang:system_info(end_time)]. + If a relative time is specified, the Time + value is not allowed to be negative.

+

If Dest is a pid(), it must + be a pid() of a process created on the current + runtime system instance. This process has either terminated + or not. If Dest is an + atom(), it is interpreted as the name of a + locally registered process. The process referred to by the + name is looked up at the time of timer expiration. No error + is returned if the name does not refer to a process.

+

If Dest is a pid(), the timer is + automatically canceled if the process referred to by the + pid() is not alive, or if the process exits. This + feature was introduced in ERTS 5.4.11. Notice that + timers are not automatically canceled when + Dest is an atom().

See also erlang:send_after/4, - erlang:cancel_timer/2, - and - erlang:read_timer/2.

+ + erlang:cancel_timer/2, and + + erlang:read_timer/2.

Failure: badarg if the arguments do not satisfy the requirements specified here.

@@ -5988,22 +6025,25 @@ true Information about active processes and ports. - -

- Returns a list where each element represents the amount - of active processes and ports on each run queue and its - associated scheduler. That is, the number of processes and - ports that are ready to run, or are currently running. The - element location in the list corresponds to the scheduler - and its run queue. The first element corresponds to scheduler - number 1 and so on. The information is not gathered - atomically. That is, the result is not necessarily a - consistent snapshot of the state, but instead quite - efficiently gathered. See also, - statistics(total_active_tasks), - statistics(run_queue_lengths), and - statistics(total_run_queue_lengths). -

+ + +

Returns a list where each element represents the amount + of active processes and ports on each run queue and its + associated scheduler. That is, the number of processes and + ports that are ready to run, or are currently running. The + element location in the list corresponds to the scheduler + and its run queue. The first element corresponds to scheduler + number 1 and so on. The information is not gathered + atomically. That is, the result is not necessarily a + consistent snapshot of the state, but instead quite + efficiently gathered.

+

See also + + statistics(total_active_tasks), + + statistics(run_queue_lengths), and + + statistics(total_run_queue_lengths).

@@ -6022,11 +6062,13 @@ true

Returns the number of exact reductions.

-

statistics(exact_reductions) is - a more expensive operation than - statistics(reductions), - especially on an Erlang machine with SMP support.

-
+ +

statistics(exact_reductions) is + a more expensive operation than + + statistics(reductions), + especially on an Erlang machine with SMP support.

+
@@ -6035,7 +6077,7 @@ true Information about garbage collection.

Returns information about garbage collection, for example:

-
+        
 > statistics(garbage_collection).
 {85,23961,0}

This information can be invalid for some implementations.

@@ -6047,9 +6089,9 @@ true
Information about I/O.

Returns Input, - which is the total number of bytes - received through ports, and Output, - which is the total number of bytes output to ports.

+ which is the total number of bytes + received through ports, and Output, + which is the total number of bytes output to ports.

@@ -6058,23 +6100,21 @@ true Information about microstate accounting. -

- Microstate accounting can be used to measure how much time the Erlang +

Microstate accounting can be used to measure how much time the Erlang runtime system spends doing various tasks. It is designed to be as - lightweight as possible, but there will be some overhead when this + lightweight as possible, but some overhead exists when this is enabled. Microstate accounting is meant to be a profiling tool - to help figure out performance bottlenecks. - To start/stop/reset microstate_accounting you use - the system_flag - - microstate_accounting. -

-

- erlang:statistics(microstate_accounting) returns a list of maps - representing some of the OS threads within ERTS. Each map contains - type and id fields that can be used to identify what + to help finding performance bottlenecks. + To start/stop/reset microstate accounting, use + system flag + microstate_accounting.

+

statistics(microstate_accounting) returns a list of maps + representing some of the OS threads within ERTS. Each map + contains type and id fields that can be used to + identify what thread it is, and also a counters field that contains data about how much time has been spent in the various states.

+

Example:

 > erlang:statistics(microstate_accounting).
 [#{counters => #{aux => 1899182914,
@@ -6085,12 +6125,11 @@ true
port => 221631, sleep => 5150294100}, id => 1, - type => scheduler}|...] - + type => scheduler}|...]

The time unit is the same as returned by - - os:perf_counter/0. - So to convert it to milliseconds you could do something like this:

+ + os:perf_counter/0 in Kernel. + So, to convert it to milliseconds, you can do something like this:

 lists:map(
   fun(#{ counters := Cnt } = M) ->
@@ -6098,39 +6137,36 @@ lists:map(
                                    erlang:convert_time_unit(PerfCount, perf_counter, 1000)
                            end, Cnt),
          M#{ counters := MsCnt }
-  end, erlang:statistics(microstate_accounting)).
-        
-

- It is important to note that these values are not guaranteed to be + end, erlang:statistics(microstate_accounting)). +

Notice that these values are not guaranteed to be the exact time spent in each state. This is because of various - optimisation done in order to keep the overhead as small as possible. -

- -

Currently the following MSAcc_Thread_Type are available:

+ optimisation done to keep the overhead as small as possible.

+

MSAcc_Thread_Types:

scheduler The main execution threads that do most of the work. - asyncAsync threads are used by various - linked-in drivers (mainly the file drivers) do offload non-cpu - intensive work. - auxTakes care of any work that is not - specifically assigned to a scheduler. + async + Async threads are used by various linked-in drivers (mainly the + file drivers) do offload non-CPU intensive work. + aux + Takes care of any work that is not + specifically assigned to a scheduler. -

Currently the following MSAcc_Thread_States are available. - All states are exclusive, meaning that a thread cannot be in two states - at once. So if you add the numbers of all counters in a thread - you will get the total run-time for that thread.

+

The following MSAcc_Thread_States are available. + All states are exclusive, meaning that a thread cannot be in two + states at once. So, if you add the numbers of all counters in a + thread, you get the total runtime for that thread.

aux Time spent handling auxiliary jobs. check_io Time spent checking for new I/O events. emulator - Time spent executing erlang processes. + Time spent executing Erlang processes. gc Time spent doing garbage collection. When extra states are - enabled this is the time spent doing non-fullsweep garbage - collections. + enabled this is the time spent doing non-fullsweep garbage + collections. other Time spent doing unaccounted things. port @@ -6138,61 +6174,60 @@ lists:map( sleep Time spent sleeping. -

It is possible to add more fine grained MSAcc_Thread_States - through configure. - (e.g. ./configure --with-microstate-accounting=extra). - Enabling these states will cause a performance degradation when - microstate accounting is turned off and increase the overhead when - it is turned on.

+

More fine-grained MSAcc_Thread_States can + be added through configure (such as + ./configure --with-microstate-accounting=extra). + Enabling these states causes performance degradation when + microstate accounting is turned off and increases the overhead when + it is turned on.

alloc Time spent managing memory. Without extra states this time is - spread out over all other states. + spread out over all other states. bif - Time spent in bifs. Without extra states this time is part of - the emulator state. + Time spent in BIFs. Without extra states this time is part of + the emulator state. busy_wait Time spent busy waiting. This is also the state where a - scheduler no longer reports that it is active when using - - erlang:statistics(scheduler_wall_time). - So if you add all other states but this and sleep and then divide that - by all time in the thread you should get something very similar to the - scheduler_wall_time fraction. Without extra states this time is part - of the other state. + scheduler no longer reports that it is active when using + + statistics(scheduler_wall_time). So, if you add + all other states but this and sleep, and then divide that by all + time in the thread, you should get something very similar to the + scheduler_wall_time fraction. Without extra states this + time is part of the other state. ets - Time spent executing ETS bifs. Without extra states this time is - part of the emulator state. + Time spent executing ets BIFs. Without extra states + this time is part of the emulator state. gc_full Time spent doing fullsweep garbage collection. Without extra - states this time is part of the gc state. + states this time is part of the gc state. nif - Time spent in nifs. Without extra states this time is part of - the emulator state. + Time spent in NIFs. Without extra states this time is part of + the emulator state. send Time spent sending messages (processes only). Without extra - states this time is part of the emulator state. + states this time is part of the emulator state. timers Time spent managing timers. Without extra states this time is - part of the other state. + part of the other state. -

There is a utility module called - msacc in - runtime_tools that can be used to more easily analyse these - statistics.

- -

- Returns undefined if the system flag +

The utility module + msacc in the + runtime_tools spplication can be used to more easily analyse + these statistics.

+

Returns undefined if system flag - microstate_accounting - is turned off. -

-

The list of thread information is unsorted and may appear in - different order between calls.

-

The threads and states are subject to change without any - prior notice.

+ microstate_accounting is turned off.

+

The list of thread information is unsorted and can appear in + different order between calls.

+ +

The threads and states are subject to change without any + prior notice.

+
+ Information about reductions. @@ -6202,11 +6237,12 @@ lists:map(
 > statistics(reductions).
 {2046,11}
-

As from ERTS 5.5 (OTP R11B), +

As from ERTS 5.5 (Erlang/OTP R11B), this value does not include reductions performed in current time slices of currently scheduled processes. If an exact value is wanted, use - statistics(exact_reductions).

+ + statistics(exact_reductions).

@@ -6215,15 +6251,14 @@ lists:map( Information about the run-queues. -

- Returns the total length of the run-queues. That is, the number +

Returns the total length of the run-queues. That is, the number of processes and ports that are ready to run on all available - run-queues. The information is gathered atomically. That - is, the result is a consistent snapshot of the state, but - this operation is much more expensive compared to - statistics(total_run_queue_lengths). - This especially when a large amount of schedulers is used. -

+ run-queues. The information is gathered atomically. That + is, the result is a consistent snapshot of the state, but + this operation is much more expensive compared to + + statistics(total_run_queue_lengths), + especially when a large amount of schedulers is used.

@@ -6231,19 +6266,21 @@ lists:map( Information about the run-queue lengths. -

- Returns a list where each element represents the amount - of processes and ports ready to run for each run queue. The - element location in the list corresponds to the run queue - of a scheduler. The first element corresponds to the run - queue of scheduler number 1 and so on. The information is - not gathered atomically. That is, the result is - not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered. See also, - statistics(total_run_queue_lengths), - statistics(active_tasks), and - statistics(total_active_tasks). -

+

Returns a list where each element represents the amount + of processes and ports ready to run for each run queue. The + element location in the list corresponds to the run queue + of a scheduler. The first element corresponds to the run + queue of scheduler number 1 and so on. The information is + not gathered atomically. That is, the result is + not necessarily a consistent snapshot of the state, but + instead quite efficiently gathered.

+

See also + + statistics(total_run_queue_lengths), + + statistics(active_tasks), and + + statistics(total_active_tasks).

@@ -6253,8 +6290,8 @@ lists:map(

Returns information about runtime, in milliseconds.

This is the sum of the runtime for all threads - in the Erlang runtime system and can therefore be greater - than the wall clock time.

+ in the Erlang runtime system and can therefore be greater + than the wall clock time.

Example:

 > statistics(runtime).
@@ -6266,7 +6303,7 @@ lists:map(
       
       Information about each schedulers work time.
       
-      
+        
         

Returns a list of tuples with {SchedulerId, ActiveTime, TotalTime}, where @@ -6274,7 +6311,8 @@ lists:map( ActiveTime is the duration the scheduler has been busy, and TotalTime is the total time duration since - scheduler_wall_time + + scheduler_wall_time activation. The time unit is undefined and can be subject to change between releases, OSs, and system restarts. scheduler_wall_time is only to be used to @@ -6286,28 +6324,28 @@ lists:map( that is:

Executing process code - Executing linked-in-driver or NIF code - Executing built-in-functions, or any other runtime - handling + Executing linked-in driver or NIF code + Executing BIFs, or any other runtime handling Garbage collecting Handling any other memory management -

Notice that a scheduler can also be busy even if the - OS has scheduled out the scheduler thread.

+

Notice that a scheduler can also be busy even if the + OS has scheduled out the scheduler thread.

Returns undefined if system flag - scheduler_wall_time - is turned off.

+ + scheduler_wall_time is turned off.

The list of scheduler information is unsorted and can appear in different order between calls.

-

Using scheduler_wall_time to calculate scheduler-utilization:

-
+        

Using scheduler_wall_time to calculate + scheduler-utilization:

+
 > erlang:system_flag(scheduler_wall_time, true).
 false
 > Ts0 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
 ok

Some time later the user takes another snapshot and calculates scheduler-utilization per scheduler, for example:

-
+        
 > Ts1 = lists:sort(erlang:statistics(scheduler_wall_time)), ok.
 ok
 > lists:map(fun({{I, A0, T0}, {I, A1, T1}}) ->
@@ -6320,8 +6358,9 @@ ok
  {6,0.9739235846420741},
  {7,0.973237033077876},
  {8,0.9741297293248656}]
-

Using the same snapshots to calculate a total scheduler-utilization:

-
+        

Using the same snapshots to calculate a total + scheduler-utilization:

+
 > {A, T} = lists:foldl(fun({{_, A0, T0}, {_, A1, T1}}, {Ai,Ti}) ->
 	{Ai + (A1 - A0), Ti + (T1 - T0)} end, {0, 0}, lists:zip(Ts0,Ts1)), A/T.
 0.9769136803764825
@@ -6337,17 +6376,19 @@ ok Information about active processes and ports. -

- Returns the total amount of active processes and ports in - the system. That is, the number of processes and ports that - are ready to run, or are currently running. The information - is not gathered atomically. That is, the result - is not necessarily a consistent snapshot of the state, but - instead quite efficiently gathered. See also, - statistics(active_tasks), - statistics(run_queue_lengths), and - statistics(total_run_queue_lengths). -

+

Returns the total amount of active processes and ports in + the system. That is, the number of processes and ports that + are ready to run, or are currently running. The information + is not gathered atomically. That is, the result + is not necessarily a consistent snapshot of the state, but + instead quite efficiently gathered.

+

See also + + statistics(active_tasks), + + statistics(run_queue_lengths), and + + statistics(total_run_queue_lengths).

@@ -6355,18 +6396,19 @@ ok Information about the run-queue lengths. -

- Returns the total length of the run-queues. That is, the number +

Returns the total length of the run queues. That is, the number of processes and ports that are ready to run on all available - run-queues. The information is not gathered atomically. - That is, the result is not necessarily a consistent snapshot of - the state, but much more efficiently gathered compared to - statistics(run_queue). - See also, - statistics(run_queue_lengths), - statistics(total_active_tasks), and - statistics(active_tasks). -

+ run queues. The information is not gathered atomically. + That is, the result is not necessarily a consistent snapshot of + the state, but much more efficiently gathered compared to + + statistics(run_queue).

+

See also + statistics(run_queue_lengths), + + statistics(total_active_tasks), and + + statistics(active_tasks).

@@ -6383,12 +6425,13 @@ ok - Suspends a process. + Suspend a process.

Suspends the process identified by - Suspendee. The same as calling - erlang:suspend_process(Suspendee, - []).

+ Suspendee. The same as calling + + erlang:suspend_process(Suspendee, + []).

This BIF is intended for debugging only.

@@ -6397,63 +6440,64 @@ ok - Suspends a process. + Suspend a process.

Increases the suspend count on the process identified by - Suspendee and puts it in the suspended - state if it is not - already in that state. A suspended process will not be - scheduled for execution until the process has been resumed.

-

A process can be suspended by multiple processes and can - be suspended multiple times by a single process. A suspended - process does not leave the suspended state until its suspend - count reaches zero. The suspend count of - Suspendee is decreased when - erlang:resume_process(Suspendee) - is called by the same process that called - erlang:suspend_process(Suspendee). - All increased suspend - counts on other processes acquired by a process are automatically - decreased when the process terminates.

-

The options (Opts) are as follows:

+ Suspendee and puts it in the suspended + state if it is not + already in that state. A suspended process is not + scheduled for execution until the process has been resumed.

+

A process can be suspended by multiple processes and can + be suspended multiple times by a single process. A suspended + process does not leave the suspended state until its suspend + count reaches zero. The suspend count of + Suspendee is decreased when + + erlang:resume_process(Suspendee) + is called by the same process that called + erlang:suspend_process(Suspendee). + All increased suspend + counts on other processes acquired by a process are automatically + decreased when the process terminates.

+

Options (Opts):

asynchronous - A suspend request is sent to the process identified by - Suspendee. Suspendee - eventually suspends - unless it is resumed before it could suspend. The caller - of erlang:suspend_process/2 returns immediately, - regardless of whether Suspendee has - suspended yet or not. The point in time when - Suspendee suspends cannot be deduced - from other events in the system. It is only guaranteed that - Suspendee eventually suspends - (unless it - is resumed). If option asynchronous has not - been passed, the caller of erlang:suspend_process/2 is - blocked until Suspendee has suspended. - +

A suspend request is sent to the process identified by + Suspendee. Suspendee + eventually suspends + unless it is resumed before it could suspend. The caller + of erlang:suspend_process/2 returns immediately, + regardless of whether Suspendee has + suspended yet or not. The point in time when + Suspendee suspends cannot be deduced + from other events in the system. It is only guaranteed that + Suspendee eventually suspends + (unless it + is resumed). If option asynchronous has not + been passed, the caller of erlang:suspend_process/2 is + blocked until Suspendee has suspended.

+ unless_suspending - The process identified by Suspendee is - suspended unless the calling process already is suspending - Suspendee. - If unless_suspending is combined - with option asynchronous, a suspend request is - sent unless the calling process already is suspending - Suspendee or if a suspend request - already has been sent and is in transit. If the calling - process already is suspending Suspendee, - or if combined with option asynchronous - and a send request already is in transit, - false is returned and the suspend count on - Suspendee remains unchanged. - +

The process identified by Suspendee is + suspended unless the calling process already is suspending + Suspendee. + If unless_suspending is combined + with option asynchronous, a suspend request is + sent unless the calling process already is suspending + Suspendee or if a suspend request + already has been sent and is in transit. If the calling + process already is suspending Suspendee, + or if combined with option asynchronous + and a send request already is in transit, + false is returned and the suspend count on + Suspendee remains unchanged.

+
-

If the suspend count on the process identified by - Suspendee is increased, true - is returned, otherwise false.

+

If the suspend count on the process identified by + Suspendee is increased, true + is returned, otherwise false.

This BIF is intended for debugging only.

@@ -6461,44 +6505,44 @@ ok badarg - If Suspendee is not a process identifier. - + If Suspendee is not a process identifier. + badarg - If the process identified by Suspendee - is the same process - as the process calling erlang:suspend_process/2. - + If the process identified by Suspendee + is the same process + as the process calling erlang:suspend_process/2. + badarg - If the process identified by Suspendee - is not alive. - + If the process identified by Suspendee + is not alive. + badarg - If the process identified by Suspendee - resides on another node. - + If the process identified by Suspendee + resides on another node. + badarg - If OptList is not a proper list of valid - Opts. - + If OptList is not a proper list of valid + Opts. + system_limit - If the process identified by Suspendee - has been suspended - more times by the calling process than can be represented by the - currently used internal data structures. The system limit is - higher than 2,000,000,000 suspends and will never be lower. - + If the process identified by Suspendee + has been suspended + more times by the calling process than can be represented by the + currently used internal data structures. The system limit is + > 2,000,000,000 suspends and will never be lower. +
- Sets system flag backtrace_depth. + Set system flag backtrace_depth.

Sets the maximum depth of call stack back-traces in the exit reason element of 'EXIT' tuples.

@@ -6508,7 +6552,7 @@ ok - Sets system flag cpu_topology. + Set system flag cpu_topology. @@ -6517,52 +6561,52 @@ ok

- This argument is deprecated and scheduled for - removal in ERTS 5.10/OTP R16. Instead of using this - argument, use command-line argument - +sct in - erl(1).

+ This argument is deprecated. + Instead of using this argument, use command-line argument + +sct in + erl(1).

When this argument is removed, a final CPU topology - to use is determined at emulator boot time.

+ to use is determined at emulator boot time.

Sets the user-defined CpuTopology. - The user-defined - CPU topology overrides any automatically detected - CPU topology. By passing undefined as - CpuTopology, - the system reverts to the CPU topology automatically - detected. The returned value equals the value returned - from erlang:system_info(cpu_topology) before the - change was made.

+ The user-defined + CPU topology overrides any automatically detected + CPU topology. By passing undefined as + CpuTopology, + the system reverts to the CPU topology automatically + detected. The returned value equals the value returned + from erlang:system_info(cpu_topology) before the + change was made.

Returns the old value of the flag.

The CPU topology is used when binding schedulers to logical - processors. If schedulers are already bound when the CPU - topology is changed, the schedulers are sent a request - to rebind according to the new CPU topology.

+ processors. If schedulers are already bound when the CPU + topology is changed, the schedulers are sent a request + to rebind according to the new CPU topology.

The user-defined CPU topology can also be set by passing - command-line argument - +sct to - erl(1).

+ command-line argument + +sct to + erl(1).

For information on type CpuTopology - and more, see - erlang:system_info(cpu_topology) - as well as the command-line flags - +sct and - +sbt in - erl(1).

+ and more, see + + erlang:system_info(cpu_topology) + as well as command-line flags + +sct and + +sbt in + erl(1).

- Sets system_flag_dirty_cpu_schedulers_online. + Set system_flag_dirty_cpu_schedulers_online.

- Sets the number of dirty CPU schedulers online. Range is - , where N - is the smallest of the return values of - erlang:system_info(dirty_cpu_schedulers) and - erlang:system_info(schedulers_online).

+ Sets the number of dirty CPU schedulers online. Range is + , where N + is the smallest of the return values of + erlang:system_info(dirty_cpu_schedulers) and + erlang:system_info(schedulers_online).

Returns the old value of the flag.

The number of dirty CPU schedulers online can change if the number of schedulers online changes. For example, if 12 @@ -6573,20 +6617,22 @@ ok down to 3. Similarly, the number of dirty CPU schedulers online increases proportionally to increases in the number of schedulers online.

-

The dirty schedulers functionality is experimental. - Enable support for dirty schedulers when building OTP to - try out the functionality.

+ +

The dirty schedulers functionality is experimental. + Enable support for dirty schedulers when building OTP to + try out the functionality.

For more information, see - erlang:system_info(dirty_cpu_schedulers) - and - erlang:system_info(dirty_cpu_schedulers_online).

+ + erlang:system_info(dirty_cpu_schedulers) and + + erlang:system_info(dirty_cpu_schedulers_online).

- Sets system flag fullsweep_after. + Set system flag fullsweep_after.

Sets system flag fullsweep_after. Number is a non-negative integer indicating @@ -6605,43 +6651,45 @@ ok - Set system flag microstate_accounting -

- Turns on/off microstate accounting measurements. By passing reset it is possible to reset - all counters to 0.

-

For more information see, - erlang:statistics(microstate_accounting). -

+ Set system flag microstate_accounting. + +

+ Turns on/off microstate accounting measurements. By passing reset, + all counters can be reset to 0.

+

For more information see + + statistics(microstate_accounting).

+ - Sets system flag min_heap_size. + Set system flag min_heap_size.

Sets the default minimum heap size for processes. The size - is given in words. The new min_heap_size effects + is specified in words. The new min_heap_size effects only processes spawned after the change of min_heap_size has been made. min_heap_size can be set for individual processes by using - spawn_opt/N or - process_flag/2.

+ spawn_opt/4 or + process_flag/2.

Returns the old value of the flag.

- Sets system flag min_bin_vheap_size. + Set system flag min_bin_vheap_size.

Sets the default minimum binary virtual heap size for - processes. The size is given in words. + processes. The size is specified in words. The new min_bin_vhheap_size effects only processes spawned after the change of min_bin_vhheap_size has been made. min_bin_vheap_size can be set for individual processes by using - spawn_opt/N or - process_flag/2.

+ spawn_opt/4 or + process_flag/2.

Returns the old value of the flag.

@@ -6649,241 +6697,251 @@ ok - Sets system flag max_heap_size + Set system flag max_heap_size.

Sets the default maximum heap size settings for processes. - The size is given in words. The new max_heap_size + The size is specified in words. The new max_heap_size effects only processes spawned efter the change has been made. max_heap_size can be set for individual processes using - spawn_opt/N or - process_flag/2.

+ spawn_opt/4 or + + process_flag/2.

Returns the old value of the flag.

- Sets system flag multi_scheduling. + Set system flag multi_scheduling.

If multi-scheduling is enabled, more than one scheduler thread is used by the emulator. Multi-scheduling can be blocked in two different ways. Either all schedulers but - one is blocked, or all normal schedulers but - one is blocked. When only normal schedulers are blocked - dirty schedulers are free to continue to schedule - processes.

+ one is blocked, or all normal schedulers but + one is blocked. When only normal schedulers are blocked, + dirty schedulers are free to continue to schedule + processes.

If BlockState =:= block, multi-scheduling is blocked. That is, one and only one scheduler thread will - execute. If BlockState =:= unblock and no one + execute. If BlockState =:= unblock and no one else blocks multi-scheduling, and this process has blocked only once, multi-scheduling is unblocked.

If BlockState =:= block_normal, normal - multi-scheduling is blocked. That is, only one normal scheduler - thread will execute, but multiple dirty schedulers may execute. - If BlockState =:= unblock_normal and no one + multi-scheduling is blocked. That is, only one normal scheduler + thread will execute, but multiple dirty schedulers can execute. + If BlockState =:= unblock_normal and no one else blocks normal multi-scheduling, and this process has blocked only once, normal multi-scheduling is unblocked.

-

One process can block multi-scheduling as well as normal - multi-scheduling multiple times. If a process has blocked - multiple times, it must unblock exactly as many times as it - has blocked before it has released its multi-scheduling - block. If a process that has blocked multi-scheduling or normal - multi scheduling exits, it automatically releases its blocking - of multi-scheduling and normal multi-scheduling.

+

One process can block multi-scheduling and normal + multi-scheduling multiple times. If a process has blocked + multiple times, it must unblock exactly as many times as it + has blocked before it has released its multi-scheduling + block. If a process that has blocked multi-scheduling or normal + multi-scheduling exits, it automatically releases its blocking + of multi-scheduling and normal multi-scheduling.

The return values are disabled, blocked, blocked_normal, or enabled. The returned value - describes the state just after the call to + describes the state just after the call to erlang:system_flag(multi_scheduling, BlockState) has been made. For information about the return values, see - erlang:system_info(multi_scheduling).

+ + erlang:system_info(multi_scheduling).

Blocking of multi-scheduling and normal multi-scheduling - is normally not needed. If you feel that you need to use these - features, consider it a few more times again. Blocking - multi-scheduling is only to be used as a last resort, as it is - most likely a very inefficient way to solve the problem.

+ is normally not needed. If you feel that you need to use these + features, consider it a few more times again. Blocking + multi-scheduling is only to be used as a last resort, as it is + most likely a very inefficient way to solve the problem.

See also - erlang:system_info(multi_scheduling), - erlang:system_info(normal_multi_scheduling_blockers), - erlang:system_info(multi_scheduling_blockers), and - erlang:system_info(schedulers).

+ + erlang:system_info(multi_scheduling), + + erlang:system_info(normal_multi_scheduling_blockers), + + erlang:system_info(multi_scheduling_blockers), and + + erlang:system_info(schedulers).

- Sets system flag scheduler_bind_type. + Set system flag scheduler_bind_type.

- This argument is deprecated and scheduled for - removal in ERTS 5.10/OTP R16. Instead of using this - argument, use command-line argument - +sbt in erl(1). - When this argument is removed, a final scheduler bind - type to use is determined at emulator boot time.

+ This argument is deprecated. + Instead of using this argument, use command-line argument + +sbt in + erl(1). When this argument is removed, a final scheduler bind + type to use is determined at emulator boot time.

Controls if and how schedulers are bound to logical - processors.

+ processors.

When erlang:system_flag(scheduler_bind_type, How) - is called, an asynchronous signal is sent to all schedulers - online, causing them to try to bind or unbind as requested.

+ is called, an asynchronous signal is sent to all schedulers + online, causing them to try to bind or unbind as requested.

If a scheduler fails to bind, this is often silently - ignored, as it is not always possible to verify valid - logical processor identifiers. If an error is reported, - it is reported to error_logger. To verify that the - schedulers have bound as requested, call - erlang:system_info(scheduler_bindings).

+ ignored, as it is not always possible to verify valid + logical processor identifiers. If an error is reported, + it is reported to error_logger. To verify that the + schedulers have bound as requested, call + + erlang:system_info(scheduler_bindings).

Schedulers can be bound on newer Linux, - Solaris, FreeBSD, and Windows systems, but more systems will be - supported in future releases.

+ Solaris, FreeBSD, and Windows systems, but more systems will be + supported in future releases.

In order for the runtime system to be able to bind schedulers, - the CPU topology must be known. If the runtime system fails - to detect the CPU topology automatically, it can be defined. - For more information on how to define the CPU topology, see - command-line flag +sct - in erl(1).

+ the CPU topology must be known. If the runtime system fails + to detect the CPU topology automatically, it can be defined. + For more information on how to define the CPU topology, see + command-line flag + +sct in erl(1).

The runtime system does by default not bind schedulers - to logical processors.

+ to logical processors.

If the Erlang runtime system is the only OS - process binding threads to logical processors, this - improves the performance of the runtime system. However, - if other OS processes (for example, another Erlang - runtime system) also bind threads to logical processors, - there can be a performance penalty instead. Sometimes this - performance penalty can be severe. If so, it is recommended - to not bind the schedulers.

+ process binding threads to logical processors, this + improves the performance of the runtime system. However, + if other OS processes (for example, another Erlang + runtime system) also bind threads to logical processors, + there can be a performance penalty instead. Sometimes this + performance penalty can be severe. If so, it is recommended + to not bind the schedulers.

Schedulers can be bound in different ways. Argument - How determines how schedulers are - bound and can be any of the following:

+ How determines how schedulers are + bound and can be any of the following:

unbound - -

Same as command-line argument - +sbt u in erl(1). -

+ Same as command-line argument + +sbt u in + erl(1). + no_spread - -

Same as command-line argument - +sbt ns in erl(1). -

+ Same as command-line argument + +sbt ns + in erl(1). + thread_spread - -

Same as command-line argument - +sbt ts in erl(1). -

+ Same as command-line argument + +sbt ts + in erl(1). + processor_spread - -

Same as command-line argument - +sbt ps in erl(1). -

+ Same as command-line argument + +sbt ps + in erl(1). + spread - -

Same as command-line argument - +sbt s in erl(1). -

+ Same as command-line argument + +sbt s + in erl(1). + no_node_thread_spread - -

Same as command-line argument - +sbt nnts in erl(1). -

+ Same as command-line argument + +sbt nnts + in erl(1). + no_node_processor_spread - -

Same as command-line argument - +sbt nnps in erl(1). -

+ Same as command-line argument + +sbt nnps + in erl(1). + thread_no_node_processor_spread - -

Same as command-line argument - +sbt tnnps in erl(1). -

+ Same as command-line argument + +sbt tnnps + in erl(1). + default_bind - -

Same as command-line argument - +sbt db in erl(1). -

+ Same as command-line argument + +sbt db + in erl(1). +

The returned value equals How before flag scheduler_bind_type was changed.

Failures:

notsup - -

If binding of schedulers is not supported.

+ If binding of schedulers is not supported. badarg - -

If How is not one of the documented - alternatives.

+ If How is not one of the documented + alternatives. badarg - -

If CPU topology information is unavailable.

+ If CPU topology information is unavailable.
-

The scheduler bind type can also be set by passing - command-line argument - +sbt to erl(1).

+

The scheduler bind type can also be set by passing command-line + argument + +sbt to erl(1).

For more information, see - erlang:system_info(scheduler_bind_type), - erlang:system_info(scheduler_bindings), - as well as command-line flags - +sbt - and +sct - in erl(1).

+ + erlang:system_info(scheduler_bind_type), + + erlang:system_info(scheduler_bindings), + as well as command-line flags + +sbt + and +sct + in erl(1).

- Sets system flag scheduler_wall_time. -

- Turns on or off scheduler wall time measurements.

-

For more information, see - erlang:statistics(scheduler_wall_time).

+ Set system flag scheduler_wall_time. + +

+ Turns on or off scheduler wall time measurements.

+

For more information, see + + statistics(scheduler_wall_time).

- Sets system flag schedulers_online. + Set system flag schedulers_online.

- Sets the number of schedulers online. Range is - .

+ Sets the number of schedulers online. Range is + .

Returns the old value of the flag.

If the emulator was built with support for - dirty schedulers, - changing the number of schedulers online can also change the - number of dirty CPU schedulers online. For example, if 12 - schedulers and 6 dirty CPU schedulers are online, and - system_flag/2 is used to set the number of schedulers - online to 6, then the number of dirty CPU schedulers online - is automatically decreased by half as well, down to 3. - Similarly, the number of dirty CPU schedulers online increases - proportionally to increases in the number of schedulers online.

+ + dirty schedulers, + changing the number of schedulers online can also change the + number of dirty CPU schedulers online. For example, if 12 + schedulers and 6 dirty CPU schedulers are online, and + system_flag/2 is used to set the number of schedulers + online to 6, then the number of dirty CPU schedulers online + is automatically decreased by half as well, down to 3. + Similarly, the number of dirty CPU schedulers online increases + proportionally to increases in the number of schedulers online.

For more information, see - erlang:system_info(schedulers) - and - erlang:system_info(schedulers_online).

+ + erlang:system_info(schedulers) and + + erlang:system_info(schedulers_online).

- Sets system flag trace_control_word. + Set system flag trace_control_word.

Sets the value of the node trace control word to TCW, which is to be an unsigned integer. - For more information, see the function - set_tcw - in Section "Match Specifications in Erlang" in the + For more information, see function + set_tcw + in section "Match Specifications in Erlang" in the User's Guide.

Returns the old value of the flag.

@@ -6891,32 +6949,30 @@ ok - Finalize the Time Offset + Finalize the time offset.

- Finalizes the time offset - when single - time warp mode is used. If another time warp mode - is used, the time offset state is left unchanged.

-

Returns the old state identifier. That is:

- - -

If preliminary is returned, finalization was - performed and the time offset is now final.

- - -

If final is returned, the time offset was - already in the final state. This either because another - erlang:system_flag(time_offset, finalize) call, or - because no - time warp mode is used.

- - -

If volatile is returned, the time offset - cannot be finalized because - multi - time warp mode is used.

-
+ Finalizes the time offset + when single + time warp mode is used. If another time warp mode + is used, the time offset state is left unchanged.

+

Returns the old state identifier, that is:

+ +

If preliminary is returned, finalization was + performed and the time offset is now final.

+
+

If final is returned, the time offset was + already in the final state. This either because another + erlang:system_flag(time_offset, finalize) call or + because no + time warp mode is used.

+
+

If volatile is returned, the time offset + cannot be finalized because + multi-time + warp mode is used.

+
+
@@ -6933,7 +6989,7 @@ ok - +

Returns various information about the allocators of the current system (emulator) as specified by Item:

@@ -6952,17 +7008,18 @@ ok

erlang:system_info(allocated_areas) is intended for debugging, and the content is highly implementation-dependent. The content of the results - therefore changes when needed without prior notice.

+ therefore changes when needed without prior notice.

Notice that the sum of these values is not 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. For information about the total amount of memory allocated by the emulator, see - erlang:memory/0,1.

+ + erlang:memory/0,1.

allocator - +

Returns {Allocator, Version, Features, Settings, where:

@@ -6992,27 +7049,30 @@ ok

See also "System Flags Effecting erts_alloc" in - erts_alloc(3).

+ + erts_alloc(3).

alloc_util_allocators - -

Returns a list of the names of all allocators using - the ERTS internal alloc_util framework - as atoms. For more information, see Section - "The - alloc_util framework" in erts_alloc(3).

+ +

Returns a list of the names of all allocators using + the ERTS internal alloc_util framework + as atoms. For more information, see section + The + alloc_util framework + in erts_alloc(3).

{allocator, Alloc} - +

Returns information about the specified allocator. - As from ERTS 5.6.1, the return value is a list - of {instance, InstanceNo, InstanceInfo} tuples, - where InstanceInfo contains information about - a specific instance of the allocator. If Alloc is not a - recognized allocator, undefined is returned. - If Alloc is disabled, + As from ERTS 5.6.1, the return value is a list + of {instance, InstanceNo, InstanceInfo} tuples, + where InstanceInfo contains information about + a specific instance of the allocator. + If Alloc is not a + recognized allocator, undefined is returned. + If Alloc is disabled, false is returned.

Notice that the information returned is highly implementation-dependent and can be changed or removed @@ -7021,15 +7081,14 @@ ok as it can be of interest for others it has been briefly documented.

The recognized allocators are listed in - erts_alloc(3). - Information about super carriers can be obtained from - ERTS 8.0 with {allocator, erts_mmap} or from - ERTS 5.10.4, the returned list when calling with - {allocator, mseg_alloc} also includes an - {erts_mmap, _} tuple as one element in the list.

- + erts_alloc(3). + Information about super carriers can be obtained from + ERTS 8.0 with {allocator, erts_mmap} or from + ERTS 5.10.4; the returned list when calling with + {allocator, mseg_alloc} also includes an + {erts_mmap, _} tuple as one element in the list.

After reading the erts_alloc(3) documentation, - the returned information + the returned information more or less speaks for itself, but it can be worth explaining some things. Call counts are presented by two values, the first value is giga calls, and the second @@ -7045,19 +7104,20 @@ ok The third is the maximum value since the emulator was started. -

If only one value is present, it is the current value. +

If only one value is present, it is the current value. fix_alloc memory block types are presented by two values. The first value is the memory pool size and the second value is the used memory size.

{allocator_sizes, Alloc} - -

Returns various size information for the specified - allocator. The information returned is a subset of the - information returned by - erlang:system_info({allocator, Alloc}). -

+ +

Returns various size information for the specified + allocator. The information returned is a subset of the + information returned by + + erlang:system_info({allocator, + Alloc}).

@@ -7091,69 +7151,74 @@ ok The info_list() can be extended in a future release. - - + +

Returns various information about the CPU topology of the current system (emulator) as specified by Item:

cpu_topology -

Returns the CpuTopology currently 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 exists, otherwise the - automatically detected CPU topology, - if such exists. If no CPU topology - exists, undefined is returned.

-

node refers to Non-Uniform Memory Access (NUMA) - nodes. thread refers to hardware threads - (for example, Intel hyper-threads).

+

Returns the CpuTopology currently 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 exists, otherwise the + + automatically detected CPU topology, + if such exists. If no CPU topology + exists, undefined is returned.

+

node refers to Non-Uniform Memory Access (NUMA) + nodes. thread refers to hardware threads + (for example, Intel hyper-threads).

A level in term CpuTopology can be - omitted if only one entry exists and - InfoList is empty.

-

thread can only be a sub level to core. - core can be a sub level to processor - or node. processor can be on the - top level or a sub level to node. node - can be on the top level or a sub level to - processor. 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 NUMA node. Cache hierarchy is not part of - the CpuTopology type, but will be in a - future release. Other things can also make it into the CPU - topology in a future release. In other words, expect the - CpuTopology type to change.

+ omitted if only one entry exists and + InfoList is empty.

+

thread can only be a sublevel to core. + core can be a sublevel to processor + or node. processor can be on the + top level or a sublevel to node. node + can be on the top level or a sublevel to + processor. 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 NUMA node. Cache hierarchy is not part of + the CpuTopology type, but will be in a + future release. Other things can also make it into the CPU + topology in a future release. So, expect the + CpuTopology type to change.

{cpu_topology, defined} - +

Returns the user-defined CpuTopology. - For more information, see command-line flag - +sct in - erl(1) and argument - cpu_topology.

+ For more information, see command-line flag + +sct in + erl(1) and argument + + cpu_topology.

{cpu_topology, detected} - +

Returns the automatically detected - CpuTopologyy. The - emulator detects the CPU topology on some newer - Linux, Solaris, FreeBSD, and Windows systems. - On Windows system with more than 32 logical processors, - the CPU topology is not detected.

+ CpuTopologyy. The + emulator detects the CPU topology on some newer + Linux, Solaris, FreeBSD, and Windows systems. + On Windows system with more than 32 logical processors, + the CPU topology is not detected.

For more information, see argument - cpu_topology.

+ + cpu_topology.

{cpu_topology, used}

Returns CpuTopology used by the emulator. For more information, see argument - cpu_topology.

+ + cpu_topology.

@@ -7170,13 +7235,14 @@ ok +

Returns information about the default process heap settings:

fullsweep_after

Returns {fullsweep_after, integer() >= 0}, which is the fullsweep_after garbage collection setting used by default. For more information, see - garbage_collection described in the following.

+ garbage_collection described below.

garbage_collection @@ -7185,50 +7251,52 @@ ok spawn or spawn_link uses these garbage collection settings. The default settings can be changed by using - system_flag/2. - spawn_opt/4 + + erlang:system_flag/2. + spawn_opt/4 can spawn a process that does not use the default settings.

max_heap_size -

Returns {max_heap_size, MaxHeapSize}, +

Returns {max_heap_size, MaxHeapSize}, where MaxHeapSize is the current - system-wide max heap size settings for spawned processes. - This setting can be set using the erl command line - flags +hmax, + system-wide maximum heap size settings for spawned processes. + This setting can be set using the command-line flags + +hmax, +hmaxk and - +hmaxel. It can - also be changed at run-time using + +hmaxel in + erl/1. It can also be changed at runtime using - erlang:system_flag(max_heap_size, MaxHeapSize). - For more details about the max_heap_size process flag + erlang:system_flag(max_heap_size, MaxHeapSize). + For more details about the max_heap_size process flag, see - process_flag(max_heap_size, MaxHeapSize). -

+ process_flag(max_heap_size, MaxHeapSize).

- min_heap_size + min_heap_size -

Returns {min_heap_size, MinHeapSize}, +

Returns {min_heap_size, MinHeapSize}, where MinHeapSize is the current system-wide minimum heap size for spawned processes.

- message_queue_data + + message_queue_data

Returns the default value of the message_queue_data - process flag which is either off_heap, or on_heap. - This default is set by the erl command line argument - +hmqd. For more information on the - message_queue_data process flag, see documentation of - process_flag(message_queue_data, - MQD).

+ process flag, which is either off_heap or on_heap. + This default is set by command-line argument + +hmqd in + erl/1. For more information on the + message_queue_data process flag, see documentation of + + process_flag(message_queue_data, MQD).

- min_bin_vheap_size + min_bin_vheap_size -

Returns {min_bin_vheap_size, +

Returns {min_bin_vheap_size, MinBinVHeapSize}, where MinBinVHeapSize is the current system-wide - minimum binary virtual heap size for spawned processes.

+ minimum binary virtual heap size for spawned processes.

@@ -7299,24 +7367,25 @@ ok allocated_areas, allocator, alloc_util_allocators, allocator_sizes -

See above.

+

See + above.

build_type

Returns an atom describing the build type of the runtime - system. This is normally the atom opt for optimized. - Other possible return values are debug, purify, - quantify, purecov, gcov, valgrind, - gprof, and lcnt. Possible return values - can be added or removed at any time without prior notice.

+ system. This is normally the atom opt for optimized. + Other possible return values are debug, purify, + quantify, purecov, gcov, valgrind, + gprof, and lcnt. Possible return values + can be added or removed at any time without prior notice.

c_compiler_used

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 undefined - if unknown. The second element is a term describing the - version of the compiler, or undefined if unknown.

+ compiling the runtime system. The first element is an + atom describing the name of the compiler, or undefined + if unknown. The second element is a term describing the + version of the compiler, or undefined if unknown.

check_io @@ -7333,12 +7402,13 @@ ok Erlang/OTP release that the current emulator has been set to be backward compatible with. The compatibility mode can be configured at startup by using command-line flag - +R in + +R in erl(1).

cpu_topology -

See above.

+

See above.

creation @@ -7354,22 +7424,22 @@ ok debug_compiled -

Returns true if the emulator has been debug - compiled, otherwise false.

+

Returns true if the emulator has been + debug-compiled, otherwise false.

delayed_node_table_gc

Returns the amount of time in seconds garbage collection - of an entry in a node table is delayed. This limit can be set - on startup by passing the command line flag - +zdntgc - to erl. For more information see the documentation of the - command line flag.

+ of an entry in a node table is delayed. This limit can be set + on startup by passing command-line flag + +zdntgc + to erl/1. For more information, see the documentation of + the command-line flag.

dirty_cpu_schedulers - +

Returns the number of dirty CPU scheduler threads used by the emulator. Dirty CPU schedulers execute CPU-bound native functions, such as NIFs, linked-in driver code, @@ -7381,23 +7451,31 @@ ok can be changed at any time. The number of dirty CPU schedulers can be set at startup by passing command-line flag - +SDcpu or - +SDPcpu in + +SDcpu or + +SDPcpu in erl(1).

-

Notice that the dirty schedulers functionality is +

Notice that the dirty schedulers functionality is experimental. Enable support for dirty schedulers when building OTP to try out the functionality.

See also - erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline), - erlang:system_info(dirty_cpu_schedulers_online), - erlang:system_info(dirty_io_schedulers), - erlang:system_info(schedulers), - erlang:system_info(schedulers_online), and - erlang:system_flag(schedulers_online, SchedulersOnline).

+ + erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline), + + erlang:system_info(dirty_cpu_schedulers_online), + + erlang:system_info(dirty_io_schedulers), + + erlang:system_info(schedulers), + + erlang:system_info(schedulers_online), and + + erlang:system_flag(schedulers_online, + SchedulersOnline).

dirty_cpu_schedulers_online - +

Returns the number of dirty CPU schedulers online. The return value satisfies , @@ -7406,51 +7484,60 @@ ok erlang:system_info(schedulers_online).

The number of dirty CPU schedulers online can be set at startup by passing command-line flag - +SDcpu in + +SDcpu in erl(1).

Notice that the dirty schedulers functionality is experimental. Enable support for dirty schedulers when building OTP to try out the functionality.

For more information, see - erlang:system_info(dirty_cpu_schedulers), - erlang:system_info(dirty_io_schedulers), - erlang:system_info(schedulers_online), and - erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline).

+ + erlang:system_info(dirty_cpu_schedulers), + + erlang:system_info(dirty_io_schedulers), + + erlang:system_info(schedulers_online), and + + erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline).

dirty_io_schedulers - +

Returns the number of dirty I/O schedulers as an integer. Dirty I/O schedulers execute I/O-bound native functions, such as NIFs and linked-in driver code, which cannot be managed cleanly by the normal emulator schedulers.

This value can be set at startup by passing command-line - argument +SDio + argument +SDio in erl(1).

-

Notice that the dirty schedulers functionality is +

Notice that the dirty schedulers functionality is experimental. Enable support for dirty schedulers when building OTP to try out the functionality.

For more information, see - erlang:system_info(dirty_cpu_schedulers), - erlang:system_info(dirty_cpu_schedulers_online), and - erlang:system_flag(dirty_cpu_schedulers_online, DirtyCPUSchedulersOnline).

+ + erlang:system_info(dirty_cpu_schedulers), + + erlang:system_info(dirty_cpu_schedulers_online), + and + erlang:system_flag(dirty_cpu_schedulers_online, + DirtyCPUSchedulersOnline).

dist

Returns a binary containing a string of distribution information formatted as in Erlang crash dumps. For more - information, see Section - "How to interpret the Erlang crash dumps" + information, see section + How to interpret the Erlang crash dumps in the User's Guide.

dist_buf_busy_limit - +

Returns the value of the distribution buffer busy limit - in bytes. This limit can be set at startup by passing - command-line flag - +zdbbl - to erl.

+ in bytes. This limit can be set at startup by passing + command-line flag + +zdbbl + to erl.

dist_ctrl @@ -7468,62 +7555,63 @@ ok

Returns a string containing the Erlang driver version used by the runtime system. It has the form - "<major ver>.<minor ver>".

+ + "<major ver>.<minor ver>".

dynamic_trace

Returns an atom describing the dynamic trace framework - compiled into the virtual machine. It can be - dtrace, systemtap, or none. For a - commercial or standard build, it is always none. - The other return values indicate a custom configuration - (for example, ./configure --with-dynamic-trace=dtrace). - For more information about dynamic tracing, see the - dyntrace - manual page and the - README.dtrace/README.systemtap files in the - Erlang source code top directory.

+ compiled into the virtual machine. It can be + dtrace, systemtap, or none. For a + commercial or standard build, it is always none. + The other return values indicate a custom configuration + (for example, ./configure --with-dynamic-trace=dtrace). + For more information about dynamic tracing, see + + runtime_tools:dyntrace manual page and the + README.dtrace/README.systemtap files in the + Erlang source code top directory.

dynamic_trace_probes

Returns a boolean() indicating if dynamic trace - probes (dtrace or systemtap) are built into - the emulator. This can only be true if the Virtual - Machine was built for dynamic tracing (that is, - system_info(dynamic_trace) returns - dtrace or systemtap).

+ probes (dtrace or systemtap) are built into + the emulator. This can only be true if the virtual + machine was built for dynamic tracing (that is, + system_info(dynamic_trace) returns + dtrace or systemtap).

- end_time - + end_time +

The last Erlang monotonic - time in native - time unit that - can be represented internally in the current Erlang runtime system - instance. The time between the - start time and - the end time is at least a quarter of a millennium.

+ time in native + time unit that + can be represented internally in the current Erlang runtime system + instance. The time between the + start time and + the end time is at least a quarter of a millennium.

+
elib_malloc

This option will be removed in a future release. - The return value will always be false, as the - elib_malloc allocator has been removed.

+ The return value will always be false, as the + elib_malloc allocator has been removed.

- eager_check_io + + eager_check_io -

- Returns the value of the erl command line flag - +secio - which is either true or false. See the - documentation of the command line flag for information about - the different values. -

+

Returns the value of command-line flag + +secio in + erl/1, which is either true or false. + For information about the different values, see the + documentation of the command-line flag.

ets_limit -

Returns the maximum number of ETS tables allowed. This +

Returns the maximum number of ets tables allowed. This limit can be increased at startup by passing command-line flag - +e to + +e to erl(1) or by setting environment variable ERL_MAX_ETS_TABLES before starting the Erlang runtime system.

@@ -7541,10 +7629,10 @@ ok private -

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.

+ 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.
@@ -7552,8 +7640,9 @@ ok

Returns a binary containing a string of miscellaneous system information formatted as in Erlang crash dumps. - For more information, see Section - "How to interpret the Erlang crash dumps" + For more information, see section + + How to interpret the Erlang crash dumps in the User's Guide.

kernel_poll @@ -7565,38 +7654,39 @@ ok

Returns a binary containing a string of loaded module information formatted as in Erlang crash dumps. For more - information, see Section - "How to interpret the Erlang crash dumps" - in the User's Guide.

+ information, see section + How to interpret the Erlang + crash dumps in the User's Guide.

- logical_processors + logical_processors - +

Returns the detected number of logical processors configured - in the system. The return value is either an integer, or - the atom unknown if the emulator cannot - detect the configured logical processors.

+ in the system. The return value is either an integer, or + the atom unknown if the emulator cannot + detect the configured logical processors.

- logical_processors_available + logical_processors_available - +

Returns the detected number of logical processors available - to the Erlang runtime system. The return value is either an - integer, or the atom unknown if the emulator - cannot detect the available logical processors. The number - of available logical processors is less than or equal to - the number of - logical processors online.

+ to the Erlang runtime system. The return value is either an + integer, or the atom unknown if the emulator + cannot detect the available logical processors. The number + of available logical processors is less than or equal to + the number of + logical processors online.

- logical_processors_online + logical_processors_online - +

Returns the detected number of logical processors online on - the system. The return value is either an integer, - or the atom unknown if the emulator cannot - detect logical processors online. The number of logical - processors online is less than or equal to the number of - logical processors configured.

+ the system. The return value is either an integer, + or the atom unknown if the emulator cannot + detect logical processors online. The number of logical + processors online is less than or equal to the number of + logical processors + configured.

machine @@ -7605,17 +7695,16 @@ ok modified_timing_level

Returns the modified timing-level (an integer) if - modified timing is enabled, otherwise, undefined. + modified timing is enabled, otherwise undefined. For more information about modified timing, see command-line flag - +T + +T in erl(1)

multi_scheduling - -

Returns disabled, blocked, blocked_normal, - or enabled:

+ +

Returns one of the following:

disabled @@ -7634,9 +7723,9 @@ ok

The emulator has more than one scheduler thread, but all normal scheduler threads except one are - blocked. Note that dirty schedulers are not - blocked, and may schedule Erlang processes and - execute native code.

+ blocked. Notice that dirty schedulers are not + blocked, and can schedule Erlang processes and + execute native code.

enabled @@ -7647,201 +7736,204 @@ ok

See also - erlang:system_flag(multi_scheduling, BlockState), - erlang:system_info(multi_scheduling_blockers), - erlang:system_info(normal_multi_scheduling_blockers), - and - erlang:system_info(schedulers).

+ + erlang:system_flag(multi_scheduling, BlockState), + + erlang:system_info(multi_scheduling_blockers), + + erlang:system_info(normal_multi_scheduling_blockers), + and + erlang:system_info(schedulers).

multi_scheduling_blockers - +

Returns a list of Pids when multi-scheduling is blocked, otherwise the empty list is returned. The Pids in the list - represent all the processes currently + represent all the processes currently blocking multi-scheduling. A Pid occurs only once in the list, even if the corresponding process has blocked multiple times.

See also - erlang:system_flag(multi_scheduling, BlockState), - erlang:system_info(multi_scheduling), - erlang:system_info(normal_multi_scheduling_blockers), - - and - erlang:system_info(schedulers).

+ + erlang:system_flag(multi_scheduling, BlockState), + + erlang:system_info(multi_scheduling), + + erlang:system_info(normal_multi_scheduling_blockers), + and + erlang:system_info(schedulers).

nif_version -

Returns a string containing the version of the Erlang NIF interface - used by the runtime system. It is on the form - "<major ver>.<minor ver>".

+

Returns a string containing the version of the Erlang NIF + interface used by the runtime system. It is on the form + "<major ver>.<minor ver>".

normal_multi_scheduling_blockers - +

Returns a list of Pids when - normal multi-scheduling is blocked (i.e. all normal schedulers - but one is blocked), otherwise the empty list is returned. - The Pids in the list represent all the - processes currently blocking normal multi-scheduling. - A Pid occurs only once in the list, even if - the corresponding process has blocked multiple times.

+ normal multi-scheduling is blocked (that is, all normal schedulers + but one is blocked), otherwise the empty list is returned. + The Pids in the list represent all the + processes currently blocking normal multi-scheduling. + A Pid occurs only once in the list, even if + the corresponding process has blocked multiple times.

See also - erlang:system_flag(multi_scheduling, BlockState), - erlang:system_info(multi_scheduling), - erlang:system_info(multi_scheduling_blockers), - - and - erlang:system_info(schedulers).

-
- otp_release - - + + erlang:system_flag(multi_scheduling, BlockState), + + erlang:system_info(multi_scheduling), + + erlang:system_info(multi_scheduling_blockers), + and + erlang:system_info(schedulers).

+
+ + otp_release + +

Returns a string containing the OTP release number of the - OTP release that the currently executing ERTS application is - part of.

-

As from OTP 17, the OTP release number corresponds to - the major OTP version number. No - erlang:system_info() argument gives the exact OTP - version. This is because the exact OTP version in the general case - is difficult to determine. For more information, see the description - of versions in - System principles in System Documentation.

-
- os_monotonic_time_source + OTP release that the currently executing ERTS application + is part of.

+

As from Erlang/OTP 17, the OTP release number corresponds to + the major OTP version number. No + erlang:system_info() argument gives the exact OTP + version. This is because the exact OTP version in the general case + is difficult to determine. For more information, see the + description of versions in + + System principles in System Documentation.

+
+ + os_monotonic_time_source

Returns a list containing information about the source of - OS - monotonic time that is used by the runtime system.

-

If [] is returned, no OS monotonic time is - available. The list contains two-tuples with Keys - as first element, and Values as second element. The - order of these tuples is undefined. The following - tuples can be part of the list, but more tuples can be - introduced in the future:

- - {function, Function} - -

Function is the name of the function - used. This tuple always exist if OS monotonic time is - available to the runtime system.

- - {clock_id, ClockId} - -

This tuple only exist if Function - can be used with different clocks. ClockId - corresponds to the clock identifier used when calling - Function.

- - {resolution, OsMonotonicTimeResolution} - -

Highest possible - resolution - of current OS monotonic time source as parts per - second. If no resolution information can be retrieved - from the OS, OsMonotonicTimeResolution is - set to the resolution of the time unit of - Functions return value. That is, the actual - resolution can be lower than - OsMonotonicTimeResolution. Also note that - the resolution does not say anything about the - accuracy, - and whether the - precision - do align with the resolution. You do, - however, know that the precision is not better than - OsMonotonicTimeResolution.

- - {extended, Extended} - -

Extended equals yes if - the range of time values has been extended; - otherwise, Extended equals no. The - range needs to be extended if Function - returns values that wrap fast. This typically - is the case when the return value is a 32-bit - value.

- - {parallel, Parallel} - -

Parallel equals yes if - Function is called in parallel from multiple - threads. If it is not called in parallel, because - calls needs to be serialized, Parallel equals - no.

- - {time, OsMonotonicTime} - -

OsMonotonicTime equals current OS - monotonic time in native - time unit.

-
-
- os_system_time_source + OS + monotonic time that is used by the runtime system.

+

If [] is returned, no OS monotonic time is + available. The list contains two-tuples with Keys + as first element, and Values as second element. The + order of these tuples is undefined. The following + tuples can be part of the list, but more tuples can be + introduced in the future:

+ + {function, Function} +

Function is the name of the function + used. This tuple always exists if OS monotonic time is + available to the runtime system.

+
+ {clock_id, ClockId} +

This tuple only exists if Function + can be used with different clocks. ClockId + corresponds to the clock identifier used when calling + Function.

+
+ {resolution, OsMonotonicTimeResolution} +

Highest possible + + resolution + of current OS monotonic time source as parts per + second. If no resolution information can be retrieved + from the OS, OsMonotonicTimeResolution is + set to the resolution of the time unit of + Functions return value. That is, the actual + resolution can be lower than + OsMonotonicTimeResolution. Notice that + the resolution does not say anything about the + + accuracy or whether the + + precision aligns with the resolution. You do, + however, know that the precision is not better than + OsMonotonicTimeResolution.

+
+ {extended, Extended} +

Extended equals yes if + the range of time values has been extended; + otherwise Extended equals no. The + range must be extended if Function + returns values that wrap fast. This typically + is the case when the return value is a 32-bit value.

+
+ {parallel, Parallel} +

Parallel equals yes if + Function is called in parallel from multiple + threads. If it is not called in parallel, because + calls must be serialized, Parallel equals + no.

+
+ {time, OsMonotonicTime} +

OsMonotonicTime equals current OS + monotonic time in native + time unit.

+
+
+
+ + os_system_time_source

Returns a list containing information about the source of - OS - system time that is used by the runtime system.

-

The list contains two-tuples with Keys - as first element, and Values as second element. The - order if these tuples is undefined. The following - tuples can be part of the list, but more tuples can be - introduced in the future:

- - {function, Function} - -

Function is the name of the funcion - used.

+ OS + system time that is used by the runtime system.

+

The list contains two-tuples with Keys + as first element, and Values as second element. The + order if these tuples is undefined. The following + tuples can be part of the list, but more tuples can be + introduced in the future:

+ + {function, Function} +

Function is the name of the funcion used.

- {clock_id, ClockId} - -

This tuple only exist if Function - can be used with different clocks. ClockId - corresponds to the clock identifier used when calling - Function.

+ {clock_id, ClockId} +

Exists only if Function + can be used with different clocks. ClockId + corresponds to the clock identifier used when calling + Function.

- {resolution, OsSystemTimeResolution} - -

Highest possible - resolution - of current OS system time source as parts per - second. If no resolution information can be retrieved - from the OS, OsSystemTimeResolution is - set to the resolution of the time unit of - Functions return value. That is, the actual - resolution may be lower than - OsSystemTimeResolution. Also note that - the resolution does not say anything about the - accuracy, - and whether the - precision - do align with the resolution. You do, - however, know that the precision is not better than - OsSystemTimeResolution.

+ {resolution, OsSystemTimeResolution} +

Highest possible + + resolution + of current OS system time source as parts per + second. If no resolution information can be retrieved + from the OS, OsSystemTimeResolution is + set to the resolution of the time unit of + Functions return value. That is, the actual + resolution can be lower than + OsSystemTimeResolution. Notice that + the resolution does not say anything about the + + accuracy or whether the + + precision do align with the resolution. You do, + however, know that the precision is not better than + OsSystemTimeResolution.

- {parallel, Parallel} - -

Parallel equals yes if - Function is called in parallel from multiple - threads. If it is not called in parallel, because - calls needs to be serialized, Parallel equals - no.

+ {parallel, Parallel} +

Parallel equals yes if + Function is called in parallel from multiple + threads. If it is not called in parallel, because + calls needs to be serialized, Parallel equals + no.

- {time, OsSystemTime} - -

OsSystemTime equals current OS - system time in native - time unit.

+ {time, OsSystemTime} +

OsSystemTime equals current OS + system time in native + time unit.

-
+
+
+ port_parallelism + + +

Returns the default port parallelism scheduling hint used. + For more information, see command-line argument + +spp + in erl(1).

- port_parallelism - - -

Returns the default port parallelism scheduling hint used. - For more information, see command-line argument - +spp in erl(1).

port_count

Returns the number of ports currently existing at the @@ -7855,9 +7947,10 @@ ok

Returns the maximum number of simultaneously existing ports at the local node as an integer. This limit can be configured at startup by using command-line flag - +Q in erl(1).

+ +Q in erl(1).

- process_count + + process_count

Returns the number of processes currently existing at the local node. The value is given as an integer. This is @@ -7866,74 +7959,78 @@ ok process_limit - +

Returns the maximum number of simultaneously existing processes at the local node. The value is given as an integer. This limit can be configured at startup by using - command-line flag +P - in erl(1).

+ command-line flag +P + in erl(1).

procs

Returns a binary containing a string of process and port information formatted as in Erlang crash dumps. For more - information, see Section - "How to interpret the Erlang crash dumps" + information, see section + How to interpret the Erlang crash dumps in the User's Guide.

scheduler_bind_type - -

Returns information about how the user has requested - schedulers to be bound or not bound.

-

Notice that even though a user has requested - schedulers to be bound, they can silently have failed - to bind. To inspect the scheduler bindings, call - erlang:system_info(scheduler_bindings).

-

For more information, see command-line argument - +sbt - in erl(1) and - erlang:system_info(scheduler_bindings).

+ +

Returns information about how the user has requested + schedulers to be bound or not bound.

+

Notice that although a user has requested + schedulers to be bound, they can silently have failed + to bind. To inspect the scheduler bindings, call + + erlang:system_info(scheduler_bindings).

+

For more information, see command-line argument + +sbt + in erl(1) and + + erlang:system_info(scheduler_bindings).

scheduler_bindings - -

Returns information about the currently used scheduler - bindings.

-

A tuple of a size equal to - erlang:system_info(schedulers) - is returned. The tuple elements are integers - or the atom unbound. Logical processor identifiers - are represented as integers. The Nth - element of the tuple equals the current binding for - the scheduler with the scheduler identifier equal to - N. For example, if the schedulers are bound, - element(erlang:system_info(scheduler_id), - erlang:system_info(scheduler_bindings)) returns - the identifier of the logical processor that the calling - process is executing on.

-

Notice that only schedulers online can be bound to logical - processors.

-

For more information, see command-line argument - +sbt - in erl(1) and - erlang:system_info(schedulers_online). -

+ +

Returns information about the currently used scheduler + bindings.

+

A tuple of a size equal to + + erlang:system_info(schedulers) + is returned. The tuple elements are integers + or the atom unbound. Logical processor identifiers + are represented as integers. The Nth + element of the tuple equals the current binding for + the scheduler with the scheduler identifier equal to + N. For example, if the schedulers are bound, + element(erlang:system_info(scheduler_id), + erlang:system_info(scheduler_bindings)) returns + the identifier of the logical processor that the calling + process is executing on.

+

Notice that only schedulers online can be bound to logical + processors.

+

For more information, see command-line argument + +sbt + in erl(1) and + + erlang:system_info(schedulers_online).

scheduler_id - +

Returns the scheduler ID (SchedulerId) of the scheduler thread that the calling process is executing on. SchedulerId is a positive integer, - where - . - See also - erlang:system_info(schedulers).

+ where .

+

See also + + erlang:system_info(schedulers).

schedulers - +

Returns the number of scheduler threads used by the emulator. Scheduler threads online schedules Erlang processes and Erlang ports, and execute Erlang code @@ -7941,45 +8038,57 @@ ok

The number of scheduler threads is determined at emulator boot time and cannot be changed later. However, the number of schedulers online can - be changed at any time.

+ be changed at any time.

See also - erlang:system_flag(schedulers_online, SchedulersOnline), - erlang:system_info(schedulers_online), - erlang:system_info(scheduler_id), - erlang:system_flag(multi_scheduling, BlockState), - erlang:system_info(multi_scheduling), - erlang:system_info(normal_multi_scheduling_blockers) - and - erlang:system_info(multi_scheduling_blockers).

+ + erlang:system_flag(schedulers_online, + SchedulersOnline), + + erlang:system_info(schedulers_online), + + erlang:system_info(scheduler_id), + + erlang:system_flag(multi_scheduling, BlockState), + + erlang:system_info(multi_scheduling), + + erlang:system_info(normal_multi_scheduling_blockers) + and + erlang:system_info(multi_scheduling_blockers). +

schedulers_online - +

Returns the number of schedulers online. The scheduler - identifiers of schedulers online satisfy the relationship - .

-

For more information, see - erlang:system_info(schedulers) - and - erlang:system_flag(schedulers_online, SchedulersOnline).

+ identifiers of schedulers online satisfy the relationship + .

+

For more information, see + + erlang:system_info(schedulers) and + + erlang:system_flag(schedulers_online, + SchedulersOnline).

smp_support

Returns true if the emulator has been compiled with SMP support, otherwise false is returned.

- start_time - + start_time +

The Erlang monotonic - time in native - time unit at the - time when current Erlang runtime system instance started. See also - erlang:system_info(end_time). -

+ time in native + time unit at the + time when current Erlang runtime system instance started.

+

See also + erlang:system_info(end_time).

+
system_version

Returns a string containing version number and - some important properties, such as the number of schedulers.

+ some important properties, such as the number of schedulers.

system_architecture @@ -7993,112 +8102,114 @@ ok thread_pool_size - +

Returns the number of async threads in the async thread pool used for asynchronous driver calls - (driver_async()). + ( + driver_async()). The value is given as an integer.

- - time_correction - - -

Returns a boolean value indicating whether - time correction - is enabled or not. -

- time_offset - - -

Returns the state of the time offset:

- - preliminary - -

The time offset is preliminary, and will be changed - at a later time when being finalized. The preliminary time offset - is used during the preliminary phase of the - single - time warp mode.

- - final - -

The time offset is final. This either because - no - time warp mode is used, or because the time - offset have been finalized when - single - time warp mode is used.

- - volatile - -

The time offset is volatile. That is, it can - change at any time. This is because - multi - time warp mode is used.

-
-
- time_warp_mode - + time_correction + + +

Returns a boolean value indicating whether + + time correction is enabled or not.

+
+ time_offset + + +

Returns the state of the time offset:

+ + preliminary + +

The time offset is preliminary, and will be changed + and finalized later. The preliminary time offset + is used during the preliminary phase of the + + single time warp mode.

+
+ final + +

The time offset is final. This either because + + no time warp mode is used, or because the time + offset have been finalized when + + single time warp mode is used.

+
+ volatile + +

The time offset is volatile. That is, it can + change at any time. This is because + + multi-time warp mode is used.

+
+
+
+ + time_warp_mode +

Returns a value identifying the - time warp - mode being used:

- - no_time_warp - -

The no - time warp mode is used.

- - single_time_warp - -

The single - time warp mode is used.

- - multi_time_warp - -

The multi - time warp mode is used.

-
-
+ + time warp mode that is used:

+ + no_time_warp + The + no time warp mode is used. + + single_time_warp + The + single time warp mode is used. + + multi_time_warp + The + multi-time warp mode is used. + + +
tolerant_timeofday - -

Returns whether a pre erts-7.0 backwards compatible compensation - for sudden changes of system time is enabled or disabled. - Such compensation is enabled when the - time offset is - final, and - time correction - is enabled.

+ +

Returns whether a pre ERTS 7.0 backwards compatible + compensation for sudden changes of system time is enabled + or disabled. Such compensation is enabled when the + time offset + is final, and + + time correction is enabled.

trace_control_word

Returns the value of the node trace control word. For - more information, see function get_tcw in Section - Match Specifications in Erlang in the User's Guide.

+ more information, see function get_tcw in section + + Match Specifications in Erlang in the User's Guide.

update_cpu_info - +

The runtime system rereads the CPU information available - and updates its internally stored information about the - detected - CPU topology and the number of logical processors - configured, - online, and - available.

-

If the CPU information has changed since the last time - it was read, the atom changed is returned, otherwise - the atom unchanged. If the CPU information has changed, - you probably want to - adjust the - number of schedulers online. You typically want - to have as many schedulers online as - logical - processors available.

+ and updates its internally stored information about the + detected + CPU topology and the number of logical processors + configured, + online, + and + available.

+

If the CPU information has changed since the last time + it was read, the atom changed is returned, otherwise + the atom unchanged. If the CPU information has changed, + you probably want to + adjust the + number of schedulers online. You typically want + to have as many schedulers online as + logical + processors available.

version - +

Returns a string containing the version number of the emulator.

@@ -8117,11 +8228,11 @@ ok {wordsize, external} -

Returns the true word size of the emulator, that is, - the size of a pointer. The value is given in bytes - as an integer. On a pure 32-bit architecture, 4 is - returned. On both a half word and on a pure - 64-bit architecture, 8 is returned.

+

Returns the true word size of the emulator, that is, + the size of a pointer. The value is given in bytes + as an integer. On a pure 32-bit architecture, 4 is + returned. On both a half word and on a pure + 64-bit architecture, 8 is returned.

@@ -8140,32 +8251,35 @@ ok

Returns the current system monitoring settings set by - erlang:system_monitor/2 + + erlang:system_monitor/2 as {MonitorPid, Options}, - or undefined if there - are no settings. The order of the options can be different - from the one that was set.

+ or undefined if no settings exist. The order of the + options can be different from the one that was set.

- Sets or clears system performance monitoring options. + Set or clear system performance monitoring options.

When called with argument undefined, all system performance monitoring settings are cleared.

Calling the function with {MonitorPid, Options} as argument is the same as calling - erlang:system_monitor(MonitorPid, Options).

+ + erlang:system_monitor(MonitorPid, + Options).

Returns the previous system monitor settings just like - erlang:system_monitor/0.

+ + erlang:system_monitor/0.

- Sets system performance monitoring options. + Set system performance monitoring options.

Sets the system performance monitoring options. @@ -8184,12 +8298,12 @@ ok

One of the tuples is {timeout, GcTime}, where GcTime is the time for the garbage collection in milliseconds. The other tuples are - tagged with heap_size, heap_block_size + tagged with heap_size, heap_block_size, stack_size, mbuf_size, old_heap_size, and old_heap_block_size. These tuples are explained in the description of trace message - gc_minor_start (see - erlang:trace/3). + gc_minor_start + (see erlang:trace/3). New tuples can be added, and the order of the tuples in the Info list can be changed at any time without prior notice.

@@ -8220,7 +8334,7 @@ ok timeout, ready_input, ready_output, event, and outputv (when the port is used by distribution). Value Millis in - the timeout tuple informs about the + tuple timeout informs about the uninterrupted execution time of the process or port, which always is equal to or higher than the Time value supplied when starting the trace. New tuples can be @@ -8231,7 +8345,7 @@ ok drivers that take too long to execute. 1 ms is considered a good maximum time for a driver callback or a NIF. However, a time-sharing system is usually to - consider everything below 100 ms as "possible" and + consider everything < 100 ms as "possible" and fairly "normal". However, longer schedule times can indicate swapping or a misbehaving NIF/driver. Misbehaving NIFs and drivers can cause bad resource @@ -8249,10 +8363,11 @@ ok

The monitor message is sent if the sum of the sizes of all memory blocks allocated for all heap generations after a garbage collection is equal to or higher than Size.

-

When a process is killed by +

When a process is killed by + max_heap_size, it is killed before the garbage collection is complete and thus no large heap message - will be sent.

+ is sent.

busy_port @@ -8274,7 +8389,8 @@ ok

Returns the previous system monitor settings just like - erlang:system_monitor/0.

+ + erlang:system_monitor/0.

If a monitoring process gets so large that it itself starts to cause system monitor messages when garbage @@ -8299,7 +8415,8 @@ ok

Returns the current system profiling settings set by - erlang:system_profile/2 + + erlang:system_profile/2 as {ProfilerPid, Options}, or undefined if there are no settings. The order of the options can be different @@ -8319,106 +8436,116 @@ ok exclusive -

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 - inactive, and later active when the port - callback returns.

+

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 + inactive, and later active when the port + callback returns.

monotonic_timestamp -

Timestamps in profile messages will use - Erlang - monotonic time. The time-stamp (Ts) has the same - format and value as produced by - erlang:monotonic_time(nano_seconds).

+

Time stamps in profile messages use + Erlang + monotonic time. The time stamp (Ts) has the same + format and value as produced by + erlang:monotonic_time(nano_seconds).

runnable_procs -

If a process is put into or removed from the run queue, a - message, {profile, Pid, State, Mfa, Ts}, is sent to - ProfilerPid. Running processes that - are reinserted into the run queue after having been - preempted do not trigger this message.

+

If a process is put into or removed from the run queue, a + message, {profile, Pid, State, Mfa, Ts}, is sent to + ProfilerPid. Running processes that + are reinserted into the run queue after having been + pre-empted do not trigger this message.

runnable_ports -

If a port is put into or removed from the run queue, a - message, {profile, Port, State, 0, Ts}, is sent to - ProfilerPid.

+

If a port is put into or removed from the run queue, a + message, {profile, Port, State, 0, Ts}, is sent to + ProfilerPid.

scheduler -

If a scheduler is put to sleep or awoken, a message, - {profile, scheduler, Id, State, NoScheds, Ts}, is - sent to ProfilerPid.

+

If a scheduler is put to sleep or awoken, a message, + {profile, scheduler, Id, State, NoScheds, Ts}, is + sent to ProfilerPid.

strict_monotonic_timestamp -

Timestamps in profile messages will consisting of - Erlang - monotonic time and a monotonically increasing - integer. The time-stamp (Ts) has the same format and value - as produced by {erlang:monotonic_time(nano_seconds), - erlang:unique_integer([monotonic])}.

+

Time stamps in profile messages consist of + Erlang + monotonic time and a monotonically increasing + integer. The time stamp (Ts) has the same format and value + as produced by {erlang:monotonic_time(nano_seconds), + erlang:unique_integer([monotonic])}.

timestamp -

Timestamps in profile messages will include a - time-stamp (Ts) that has the same form as returned by - erlang:now(). This is also the default if no - timestamp flag is given. If cpu_timestamp has - been enabled via erlang:trace/3, this will also - effect the timestamp produced in profiling messages - when timestamp flag is enabled.

+

Time stamps in profile messages include a + time stamp (Ts) that has the same form as returned by + erlang:now(). This is also the default if no + time stamp flag is specified. If cpu_timestamp has + been enabled through + erlang:trace/3, + this also effects the time stamp produced in profiling messages + when flag timestamp is enabled.

-

erlang:system_profile is considered experimental - and its behavior can change in a future release.

+ +

erlang:system_profile is considered experimental + and its behavior can change in a future release.

+ - Current Erlang system time - -

Returns current - Erlang system time - in native - time unit.

- -

Calling erlang:system_time() is equivalent to: - erlang:monotonic_time() - + - erlang:time_offset().

- -

This time is not a monotonically increasing time - in the general case. For more information, see the documentation of - time warp modes in the - ERTS User's Guide.

+ Current Erlang system time. + +

Returns current + + Erlang system time in native + time unit.

+

Calling erlang:system_time() is equivalent to + + erlang:monotonic_time() + + + erlang:time_offset().

+ +

This time is not a monotonically increasing time + in the general case. For more information, see the documentation of + + time warp modes in the User's Guide.

+
+ - Current Erlang system time - -

Returns current - Erlang system time - converted into the Unit passed as argument.

- -

Calling erlang:system_time(Unit) is equivalent to: - erlang:convert_time_unit(erlang:system_time(), - native, Unit).

- -

This time is not a monotonically increasing time - in the general case. For more information, see the documentation of - time warp modes in the - ERTS User's Guide.

+ Current Erlang system time. + +

Returns current + + Erlang system time + converted into the Unit passed as argument.

+

Calling erlang:system_time(Unit) is equivalent + to + erlang:convert_time_unit(erlang:system_time(), + native, Unit).

+ +

This time is not a monotonically increasing time + in the general case. For more information, see the documentation of + + time warp modes in the User's Guide.

+
+ - Encodes a term to an Erlang external term format binary. + Encode a term to an Erlang external term format binary. +

Returns a binary data object that is the result of encoding Term according to the Erlang external @@ -8427,64 +8554,65 @@ ok 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.

-

See also - binary_to_term/1.

+

See also + binary_to_term/1.

- Encodes a term to en Erlang external term format binary. + Encode a term to en Erlang external term format binary. +

Returns a binary data object that is the result of encoding Term according to the Erlang external term format.

If option compressed is provided, the external term format is compressed. The compressed format is automatically - recognized by binary_to_term/1 as from Erlang R7B.

+ recognized by binary_to_term/1 as from Erlang/OTP R7B.

A compression level can be specified by giving option {compressed, Level}. Level is an integer with range 0..9, where:

- 0 - No compression is done (it is the same as - giving no compressed option). - 1 - Takes least time but may not compress - as well as the higher levels. - 6 - Default level when option compressed - is provided. - 9 - Takes most time and tries to produce a smaller +

0 - No compression is done (it is the same as + giving no compressed option).

+

1 - Takes least time but may not compress + as well as the higher levels.

+

6 - Default level when option compressed + is provided.

+

9 - Takes most time and tries to produce a smaller result. Notice "tries" in the preceding sentence; depending on the input term, level 9 compression either does or does - not produce a smaller result than level 1 compression. + not produce a smaller result than level 1 compression.

Option {minor_version, Version} - can be used to control - some encoding details. This option was introduced in OTP R11B-4. + can be used to control some + encoding details. This option was introduced in Erlang/OTP R11B-4. The valid values for Version are 0 and 1.

-

As from OTP 17.0, {minor_version, 1} is the default. It +

As from Erlang/OTP 17.0, {minor_version, 1} is the default. It forces any floats in the term to be encoded in a more space-efficient and exact way (namely in the 64-bit IEEE format, rather than converted to a textual representation).

-

As from OTP R11B-4, binary_to_term/1 can decode this +

As from Erlang/OTP R11B-4, binary_to_term/1 can decode this representation.

{minor_version, 0} means that floats are encoded using a textual representation. This option is useful to - ensure that releases before OTP R11B-4 can decode resulting + ensure that releases before Erlang/OTP R11B-4 can decode resulting binary.

-

See also - binary_to_term/1.

+

See also + binary_to_term/1.

- Throws an exception. + Throw an exception.

A non-local return from a function. If evaluated within a - catch, catch returns value Any.

-

Example:

+ catch, catch returns value Any. + Example:

 > catch throw({hello, there}).
 {hello,there}
@@ -8498,8 +8626,7 @@ ok

Returns the current time as {Hour, Minute, Second}.

The time zone and Daylight Saving Time correction depend on - the underlying OS.

-

Example:

+ the underlying OS. Example:

 > time().
 {9,42,44}
@@ -8508,86 +8635,94 @@ ok - Current time offset - -

Returns the current time offset between - Erlang monotonic time - and - Erlang system time in - native time unit. - Current time offset added to an Erlang monotonic time gives - corresponding Erlang system time.

- -

The time offset may or may not change during operation depending - on the time - warp mode used.

- - -

A change in time offset may be observed at slightly - different points in time by different processes.

- -

If the runtime system is in - multi - time warp mode, the time offset will be changed when - the runtime system detects that the - OS system - time has changed. The runtime system will, however, - not detect this immediately when it happens. A task checking - the time offset is scheduled to execute at least once a minute, - so under normal operation this should be detected within a - minute, but during heavy load it might take longer time.

-
+ Current time offset. + +

Returns the current time offset between + + Erlang monotonic time and + + Erlang system time in + native time unit. + Current time offset added to an Erlang monotonic time gives + corresponding Erlang system time.

+

The time offset may or may not change during operation depending + on the time + warp mode used.

+ +

A change in time offset can be observed at slightly + different points in time by different processes.

+

If the runtime system is in + multi-time + warp mode, the time offset is changed when + the runtime system detects that the + OS system + time has changed. The runtime system will, however, + not detect this immediately when it occurs. A task checking + the time offset is scheduled to execute at least once a minute; + so, under normal operation this is to be detected within a + minute, but during heavy load it can take longer time.

+
+ - Current time offset + Current time offset. -

Returns the current time offset between - Erlang monotonic time - and - Erlang system time - converted into the Unit passed as argument.

- -

Same as calling - erlang:convert_time_unit(erlang:time_offset(), native, Unit) - however optimized for commonly used Units.

+

Returns the current time offset between + + Erlang monotonic time and + + Erlang system time + converted into the Unit passed as argument.

+

Same as calling + + erlang:convert_time_unit( + erlang:time_offset(), native, + Unit) + however optimized for commonly used Units.

+ - Current Erlang System time + Current Erlang System time. -

Returns current - Erlang system time - on the format {MegaSecs, Secs, MicroSecs}. This format is - the same as os:timestamp/0 - and the deprecated erlang:now/0 - uses. The reason for the existence of erlang:timestamp() is - purely to simplify usage for existing code that assumes this timestamp - format. Current Erlang system time can more efficiently be retrieved in - the time unit of your choice using - erlang:system_time/1.

- -

The erlang:timestamp() BIF is equivalent to:

+

Returns current + + Erlang system time + on the format {MegaSecs, Secs, MicroSecs}. This format is + the same as + os:timestamp/0 + and the deprecated + erlang:now/0 + use. The reason for the existence of erlang:timestamp() is + purely to simplify use for existing code that assumes this time stamp + format. Current Erlang system time can more efficiently be retrieved + in the time unit of your choice using + + erlang:system_time/1.

+

The erlang:timestamp() BIF is equivalent to:

+ timestamp() -> ErlangSystemTime = erlang:system_time(micro_seconds), MegaSecs = ErlangSystemTime div 1000000000000, Secs = ErlangSystemTime div 1000000 - MegaSecs*1000000, MicroSecs = ErlangSystemTime rem 1000000, {MegaSecs, Secs, MicroSecs}. -

It, however, uses a native implementation which does - not build garbage on the heap and with slightly better - performance.

- -

This time is not a monotonically increasing time - in the general case. For more information, see the documentation of - time warp modes in the - ERTS User's Guide.

+

It, however, uses a native implementation that does + not build garbage on the heap and with slightly better + performance.

+ +

This time is not a monotonically increasing time + in the general case. For more information, see the documentation of + + time warp modes in the User's Guide.

+
-
+ Tail of a list. @@ -8605,7 +8740,7 @@ timestamp() -> - Sets trace flags for a process or processes. + Set trace flags for a process or processes.

Turns on (if How == true) or off (if @@ -8615,49 +8750,43 @@ timestamp() -> PidPortSpec.

PidPortSpec is either a process identifier (pid) for a local process, a port identifier, - or one of the following atoms:

+ or one of the following atoms:

all - -

All currently existing processes and ports and all that - will be created in the future.

+ All currently existing processes and ports and all that + will be created in the future. processes - -

All currently existing processes and all that will be created in the future.

+ All currently existing processes and all that will be created + in the future. ports - -

All currently existing ports and all that will be created in the future.

+ All currently existing ports and all that will be created in + the future. existing - -

All currently existing processes and ports.

+ All currently existing processes and ports. existing_processes - -

All currently existing processes.

+ All currently existing processes. existing_ports - -

All currently existing ports.

+ All currently existing ports. new - -

All processes and ports that will be created in the future.

+ All processes and ports that will be created in the future. new_processes - -

All processes that will be created in the future.

+ All processes that will be created in the future. new_ports - -

All ports that will be created in the future.

+ All ports that will be created in the future.

FlagList can contain any number of the following flags (the "message tags" refers to the list of - trace messages):

+ + trace messages):

all @@ -8668,21 +8797,29 @@ timestamp() -> send

Traces sending of messages.

-

Message tags: send and - send_to_non_existing_process.

+

Message tags: + + send and + + send_to_non_existing_process.

'receive'

Traces receiving of messages.

-

Message tags: 'receive'.

+

Message tags: + + 'receive'.

-call + call

Traces certain function calls. Specify which function - calls to trace by calling - erlang:trace_pattern/3.

-

Message tags: call and - return_from.

+ calls to trace by calling + erlang:trace_pattern/3.

+

Message tags: + + call and + + return_from.

silent @@ -8700,17 +8837,21 @@ timestamp() -> specification function {silent,Bool}, giving a high degree of control of which functions with which arguments that trigger the trace.

-

Message tags: call, - return_from, and - return_to. Or rather, the absence of.

+

Message tags: + + call, + + return_from, and + + return_to. Or rather, the absence of.

return_to

Used with the call trace flag. Traces the return from a traced function back to its caller. Only works for functions traced with - option local to - erlang:trace_pattern/3.

+ option local to + erlang:trace_pattern/3.

The semantics is that a trace message is sent when a call traced function returns, that is, when a chain of tail recursive calls ends. Only one trace @@ -8723,105 +8864,144 @@ timestamp() ->

To get trace messages containing return values from functions, use the {return_trace} match specification action instead.

-

Message tags: return_to.

+

Message tags: + + return_to.

procs

Traces process-related events.

-

Message tags: spawn, - spawned, - exit, - register, - unregister, - link, - unlink, - getting_linked, and - getting_unlinked.

+

Message tags: + + spawn, + + spawned, + + exit, + + register, + + unregister, + + link, + + unlink, + + getting_linked, and + + getting_unlinked.

ports

Traces port-related events.

-

Message tags: open, - closed, - register, - unregister, - getting_linked, and - getting_unlinked.

+

Message tags: + + open, + + closed, + + register, + + unregister, + + getting_linked, and + + getting_unlinked.

running

Traces scheduling of processes.

-

Message tags: in and - out.

+

Message tags: + + in and + + out.

exiting

Traces scheduling of exiting processes.

-

Message tags: in_exiting, - out_exiting, and - out_exited.

+

Message tags: + + in_exiting, + + out_exiting, and + + out_exited.

running_procs

Traces scheduling of processes just like running. - However this option also includes schedule events when the - process executes within the context of a port without - being scheduled out itself.

-

Message tags: in and - out.

+ However, this option also includes schedule events when the + process executes within the context of a port without + being scheduled out itself.

+

Message tags: + + in and + + out.

running_ports

Traces scheduling of ports.

-

Message tags: in and - out.

+

Message tags: + + in and + + out.

garbage_collection

Traces garbage collections of processes.

-

Message tags: gc_minor_start, - gc_max_heap_size and - gc_minor_end.

+

Message tags: + + gc_minor_start, + + gc_max_heap_size, and + + gc_minor_end.

timestamp -

Includes a time-stamp in all trace messages. The - time-stamp (Ts) has the same form as returned by +

Includes a time stamp in all trace messages. The + time stamp (Ts) has the same form as returned by erlang:now().

cpu_timestamp

A global trace flag for the Erlang node that makes all - trace time-stamps using the timestamp flag to be - in CPU time, not wall clock time. That is, cpu_timestamp - will not be used if monotonic_timestamp, or - strict_monotonic_timestamp is enabled. + trace time stamps using flag timestamp to be + in CPU time, not wall clock time. That is, cpu_timestamp + is not be used if monotonic_timestamp or + strict_monotonic_timestamp is enabled. Only allowed with PidPortSpec==all. If the host machine OS does not support high-resolution CPU time measurements, trace/3 exits with badarg. Notice that most OS do not synchronize this value across cores, so be prepared - that time might seem to go backwards when using this option.

+ that time can seem to go backwards when using this option.

monotonic_timestamp

Includes an - Erlang - monotonic time time-stamp in all trace messages. The - time-stamp (Ts) has the same format and value as produced by - erlang:monotonic_time(nano_seconds). - This flag overrides the cpu_timestamp flag.

+ Erlang + monotonic time time stamp in all trace messages. The + time stamp (Ts) has the same format and value as produced by + + erlang:monotonic_time(nano_seconds). + This flag overrides flag cpu_timestamp.

strict_monotonic_timestamp -

Includes an timestamp consisting of - Erlang - monotonic time and a monotonically increasing - integer in all trace messages. The time-stamp (Ts) has the - same format and value as produced by - {erlang:monotonic_time(nano_seconds), - erlang:unique_integer([monotonic])}. - This flag overrides the cpu_timestamp flag.

+

Includes an time stamp consisting of + Erlang + monotonic time and a monotonically increasing + integer in all trace messages. The time stamp (Ts) has the + same format and value as produced by { + + erlang:monotonic_time(nano_seconds), + + erlang:unique_integer([monotonic])}. + This flag overrides flag cpu_timestamp.

arity @@ -8859,34 +9039,34 @@ timestamp() -> {tracer, TracerModule, TracerState} -

Specifies that a tracer module should be called - instead of sending a trace message. The tracer module - can then ignore or change the trace message. For more details - on how to write a tracer module see - erl_tracer -

+

Specifies that a tracer module is to be called + instead of sending a trace message. The tracer module + can then ignore or change the trace message. For more details + on how to write a tracer module, see + erl_tracer.

-

If no tracer is given, the calling process - will be receiving all of the trace messages

+

If no tracer is specified, the calling process + receives all the trace messages.

The effect of combining set_on_first_link with - set_on_link is the same as having + set_on_link is the same as set_on_first_link alone. Likewise for set_on_spawn and set_on_first_spawn.

The tracing process receives the trace messages described - in the following list. Pid is the process identifier of the - traced process in which the traced event has occurred. The - third tuple element is the message tag.

+ in the following list. Pid is the process identifier of the + traced process in which the traced event has occurred. The + third tuple element is the message tag.

If flag timestamp, strict_monotonic_timestamp, or - monotonic_timestamp is given, the first tuple - element is trace_ts instead, and the time-stamp - is added as an extra element last in the message tuple. If - multiple timestamp flags are passed, timestamp has - precedence over strict_monotonic_timestamp which - in turn has precedence over monotonic_timestamp. All - timestamp flags are remembered, so if two are passed - and the one with highest precedence later is disabled - the other one will become active.

+ monotonic_timestamp is specified, the first tuple + element is trace_ts instead, and the time stamp + is added as an extra element last in the message tuple. If + multiple time stamp flags are passed, timestamp has + precedence over strict_monotonic_timestamp, which + in turn has precedence over monotonic_timestamp. All + time stamp flags are remembered, so if two are passed + and the one with highest precedence later is disabled, + the other one becomes active.

+

Trace messages:

@@ -8898,7 +9078,7 @@ timestamp() -> process To.

- + {trace, PidPort, send_to_non_existing_process, Msg, To} @@ -8911,9 +9091,9 @@ timestamp() ->

When PidPort receives message Msg. - If Msg is set to timeout, then a receive - statement may have timedout, or the process received - a message with the payload timeout.

+ If Msg is set to time-out, a receive + statement can have timed out, or the process received + a message with the payload timeout.

@@ -9047,7 +9227,7 @@ timestamp() ->

When Pid opens a new port Port with - the running the Driver.

+ the running Driver.

Driver is the name of the driver as an atom.

@@ -9055,7 +9235,7 @@ timestamp() -> {trace, Port, closed, Reason} -

When Port closed with Reason.

+

When Port closes with Reason.

@@ -9072,7 +9252,8 @@ timestamp() -> - {trace, Pid, out | out_exiting | out_exited, {M, F, Arity} | 0} + {trace, Pid, out | out_exiting | out_exited, {M, F, Arity} + | 0}

When Pid is scheduled out. The process was @@ -9086,11 +9267,13 @@ timestamp() ->

When Port is scheduled to run. Command is the - first thing the port will execute, it may however run several - commands before being scheduled out. On some rare - occasions, the current function cannot be determined, - then the last element is 0.

-

The possible commands are: call | close | command | connect | control | flush | info | link | open | unlink

+ first thing the port will execute, it can however run several + commands before being scheduled out. On some rare + occasions, the current function cannot be determined, + then the last element is 0.

+

The possible commands are call, close, + command, connect, control, flush, + info, link, open, and unlink.

@@ -9101,8 +9284,7 @@ timestamp() -> was Command. On some rare occasions, the current function cannot be determined, then the last element is 0. Command can contain the same - commands as in -

+ commands as in

@@ -9118,13 +9300,13 @@ timestamp() -> heap_size The size of the used part of the heap. - heap_block_size - The size of the memory block used for storing - the heap and the stack. + heap_block_size + The size of the memory block used for storing + the heap and the stack. old_heap_size The size of the used part of the old heap. - old_heap_block_size - The size of the memory block used for storing + old_heap_block_size + The size of the memory block used for storing the old heap. stack_size The size of the stack. @@ -9138,14 +9320,15 @@ timestamp() -> The total size of unique off-heap binaries referenced from the process heap. bin_vheap_block_size - The total size of binaries allowed in the virtual - heap in the process before doing a garbage collection. + The total size of binaries allowed in the virtual + heap in the process before doing a garbage collection. bin_old_vheap_size The total size of unique off-heap binaries referenced from the process old heap. bin_old_vheap_block_size - The total size of binaries allowed in the virtual - old heap in the process before doing a garbage collection. + The total size of binaries allowed in the virtual + old heap in the process before doing a garbage + collection.

All sizes are in words.

@@ -9154,13 +9337,12 @@ timestamp() -> {trace, Pid, gc_max_heap_size, Info}
-

- Sent when the max_heap_size +

Sent when the + max_heap_size is reached during garbage collection. Info contains the same kind of list as in message gc_start, - but the sizes reflect the sizes that triggered max_heap_size to - be reached. -

+ but the sizes reflect the sizes that triggered + max_heap_size to be reached.

@@ -9168,7 +9350,8 @@ timestamp() ->

Sent when young garbage collection is finished. Info - contains the same kind of list as in message gc_minor_start, + contains the same kind of list as in message + gc_minor_start, but the sizes reflect the new sizes after garbage collection.

@@ -9177,8 +9360,9 @@ timestamp() -> {trace, Pid, gc_major_start, Info}
-

Sent when fullsweep garbage collection is about to be started. Info - contains the same kind of list as in message gc_minor_start.

+

Sent when fullsweep garbage collection is about to be started. + Info contains the same kind of list as in message + gc_minor_start.

@@ -9186,15 +9370,16 @@ timestamp() ->

Sent when fullsweep garbage collection is finished. Info - contains the same kind of list as in message gc_minor_start - but the sizes reflect the new sizes after a fullsweep garbage collection.

+ contains the same kind of list as in message + gc_minor_start, but the sizes reflect the new sizes after + a fullsweep garbage collection.

If the tracing process/port dies or the tracer module returns - remove, the flags are silently removed.

+ remove, the flags are silently removed.

Each process can only be traced by one tracer. Therefore, attempts to trace an already traced process fail.

-

Returns: A number indicating the number of processes that +

Returns a number indicating the number of processes that matched PidPortSpec. If PidPortSpec is a process identifier, the return value is 1. @@ -9214,22 +9399,24 @@ timestamp() -> Notification when trace has been delivered.

The delivery of trace messages (generated by - erlang:trace/3, - seq_trace or - erlang:system_profile/2) + erlang:trace/3, + kernel:seq_trace, + or + erlang:system_profile/2) is dislocated on the time-line compared to other events in the system. If you know that Tracee 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, use erlang:trace_delivered(Tracee). A - {trace_delivered, Tracee, Ref} message is sent to - the caller of erlang:trace_delivered(Tracee) when it - is guaranteed that all trace messages are delivered to + tracer, use erlang:trace_delivered(Tracee).

+

When it is guaranteed that all trace messages are delivered to the tracer up to the point that Tracee reached at the time of the call to - erlang:trace_delivered(Tracee).

+ erlang:trace_delivered(Tracee), then a + {trace_delivered, Tracee, Ref} + message is sent to the caller of + erlang:trace_delivered(Tracee) .

Notice that message trace_delivered does not imply that trace messages have been delivered. Instead it implies that all trace messages that @@ -9239,22 +9426,22 @@ timestamp() -> no trace messages have been delivered when the trace_delivered message arrives.

Notice that Tracee must refer - to a process currently, + to a process currently or previously existing on the same node as the caller of erlang:trace_delivered(Tracee) resides on. The special Tracee atom all denotes all processes that currently are traced in the node.

-

When used together with an - Tracer Module any message sent in the trace callback - is guaranteed to have reached it's recipient before the +

When used together with a + Tracer Module, any message sent in the trace callback + is guaranteed to have reached its recipient before the trace_delivered message is sent.

Example: Process A is Tracee, - port B is tracer, and process C is the port - owner of B. C wants to close B when - A exits. To ensure that the trace is not truncated, - C can call erlang:trace_delivered(A), when - A exits, and wait for message {trace_delivered, A, - Ref} before closing B.

+ port B is tracer, and process C is the port + owner of B. C wants to close B when + A exits. To ensure that the trace is not truncated, + C can call erlang:trace_delivered(A) when + A exits, and wait for message {trace_delivered, A, + Ref} before closing B.

Failure: badarg if Tracee does not refer to a process (dead or alive) on the same node as the caller of @@ -9264,22 +9451,23 @@ timestamp() -> - Trace information about a process or function. + Trace information about a process or function. -

Returns trace information about a port, process, function or event.

+

Returns trace information about a port, process, function, or + event.

To get information about a port or process, - PidPortFuncEvent is to - be a process identifier (pid), port identifier or one of - the atoms new, new_processes, new_ports. - The atom new or new_processes means that the default trace - state for processes to be created is returned. The atom new_ports - means that the default trace state for ports to be created is returned. -

-

The following Items are valid for ports and processes:

+ PidPortFuncEvent is to + be a process identifier (pid), port identifier, or one of + the atoms new, new_processes, or new_ports. The + atom new or new_processes means that the default trace + state for processes to be created is returned. The atom + new_ports means that the default trace state for ports to be + created is returned.

+

Valid Items for ports and processes:

flags @@ -9288,30 +9476,32 @@ timestamp() -> traces are enabled, and one or more of the followings atoms if traces are enabled: send, 'receive', set_on_spawn, call, - return_to, procs, ports, set_on_first_spawn, + return_to, procs, ports, + set_on_first_spawn, set_on_link, running, running_procs, - running_ports, silent, exiting + running_ports, silent, exiting, monotonic_timestamp, strict_monotonic_timestamp, garbage_collection, timestamp, and arity. The order is arbitrary.

tracer -

Returns the identifier for process, port or a tuple containing +

Returns the identifier for process, port, or a tuple containing the tracer module and tracer state tracing this - process. If this process is not being traced, the return + process. If this process is not traced, the return value is [].

-

To get information about a function, PidPortFuncEvent is to +

To get information about a function, + PidPortFuncEvent is to be the three-element tuple {Module, Function, Arity} or - the atom on_load. No wild cards are allowed. Returns + the atom on_load. No wildcards are allowed. Returns undefined if the function does not exist, or - false if the function is not traced. If PidPortFuncEvent - is on_load, the information returned refers to - the default value for code that will be loaded.

- -

The following Items are valid for functions:

+ false if the function is not traced. + If PidPortFuncEvent + is on_load, the information returned refers to + the default value for code that will be loaded.

+

Valid Items for functions:

traced @@ -9330,11 +9520,12 @@ timestamp() -> meta -

Returns the meta-trace tracer process, port or trace module +

Returns the meta-trace tracer process, port, or trace module for this function, if it has one. If the function is not meta-traced, the returned value is false. If the function is meta-traced but has once detected that - the tracer process is invalid, the returned value is [].

+ the tracer process is invalid, the returned value is + [].

meta_match_spec @@ -9347,21 +9538,22 @@ timestamp() ->

Returns the call count value for this function or true for the pseudo function on_load if call - count tracing is active. Otherwise false is returned. - See also - erlang:trace_pattern/3.

+ count tracing is active. Otherwise false is returned.

+

See also + erlang:trace_pattern/3.

call_time -

Returns the call time values for this function or +

Returns the call time values for this function or true for the pseudo function on_load if call - time tracing is active. Otherwise false is returned. - The call time values returned, [{Pid, Count, S, Us}], - is a list of each process that executed the function - and its specific counters. See also - erlang:trace_pattern/3.

+ time tracing is active. Otherwise false is returned. + The call time values returned, [{Pid, Count, S, Us}], + is a list of each process that executed the function + and its specific counters.

+

See also + + erlang:trace_pattern/3.

- all

Returns a list containing the @@ -9370,80 +9562,84 @@ timestamp() -> is active for this function.

-

To get information about an event, PidPortFuncEvent is to +

To get information about an event, + PidPortFuncEvent is to be one of the atoms send or 'receive'.

-

The only valid Item for events is:

+

One valid Item for events exists:

match_spec

Returns the match specification for this event, if it has one, or true if no match specification has been - set.

+ set.

The return value is {Item, Value}, where Value is the requested information as described earlier. - If a pid for a dead process was given, or the name of a + If a pid for a dead process was specified, or the name of a non-existing function, Value is undefined.

- Sets trace patterns for call, send or 'receive' tracing. + Set trace patterns for call, send, or 'receive' tracing. +

The same as - erlang:trace_pattern(Event, MatchSpec, []), + + erlang:trace_pattern(Event, MatchSpec, []), retained for backward compatibility.

- Sets trace pattern for message sending. + Set trace pattern for message sending.

Sets trace pattern for message sending. - Must be combined with - erlang:trace/3 + Must be combined with + erlang:trace/3 to set the send trace flag for one or more processes. - By default all messages, sent from send traced processes, - are traced. Use erlang:trace_pattern/3 to limit - traced send events based on the message content, the sender - and/or the receiver.

+ By default all messages sent from send traced processes + are traced. To limit + traced send events based on the message content, the sender + and/or the receiver, use erlang:trace_pattern/3.

Argument MatchSpec can take the following forms:

MatchSpecList

A list of match specifications. The matching is done - on the list [Receiver, Msg]. Receiver - is the process or port identity of the receiver and - Msg is the message term. The pid of the sending - process can be accessed with the guard function - self/0. An empty list is the same as true. - See the users guide section - Match Specifications in Erlang - for more information.

+ on the list [Receiver, Msg]. Receiver + is the process or port identity of the receiver and + Msg is the message term. The pid of the sending + process can be accessed with the guard function + self/0. An empty list is the same as true. + For more information, see section + + Match Specifications in Erlang in the User's Guide.

true

Enables tracing for all sent messages (from send - traced processes). Any match specification is - removed. This is the default.

+ traced processes). Any match specification is + removed. This is the default.

false

Disables tracing for all sent messages. - Any match specification is removed.

+ Any match specification is removed.

-

Argument FlagList must be [] - for send tracing.

-

The return value is always 1.

-

Example; only trace messages to a specific process Pid:

+

Argument FlagList must be [] + for send tracing.

+

The return value is always 1.

+

Examples:

+

Only trace messages to a specific process Pid:

 > erlang:trace_pattern(send, [{[Pid, '_'],[],[]}], []).
 1
@@ -9459,58 +9655,60 @@ timestamp() ->
 > erlang:trace_pattern(send, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).
 1
-

A match specification for send trace can use - all guard and body functions except caller.

+ +

A match specification for send trace can use + all guard and body functions except caller.

+
- Sets trace pattern for tracing of message receiving. + Set trace pattern for tracing of message receiving. -

Sets trace pattern for message receiving. - Must be combined with - erlang:trace/3 + Must be combined with + erlang:trace/3 to set the 'receive' trace flag for one or more processes. - By default all messages, received by 'receive' traced processes, - are traced. Use erlang:trace_pattern/3 to limit - traced receive events based on the message content, the sender - and/or the receiver.

+ By default all messages received by 'receive' traced + processes are traced. To limit + traced receive events based on the message content, the sender + and/or the receiver, use erlang:trace_pattern/3.

Argument MatchSpec can take the following forms:

MatchSpecList

A list of match specifications. The matching is done - on the list [Node, Sender, Msg]. Node - is the node name of the sender. Sender is the - process or port identity of the sender, or the atom - undefined if the sender is not known (which may - be the case for remote senders). Msg is the - message term. The pid of the receiving process can be - accessed with the guard function self/0. An empty - list is the same as true. See the users guide section - Match Specifications in Erlang - for more information.

+ on the list [Node, Sender, Msg]. Node + is the node name of the sender. Sender is the + process or port identity of the sender, or the atom + undefined if the sender is not known (which can + be the case for remote senders). Msg is the + message term. The pid of the receiving process can be + accessed with the guard function self/0. An empty + list is the same as true. For more information, see + section + Match Specifications in Erlang in the User's Guide.

true

Enables tracing for all received messages (to 'receive' - traced processes). Any match specification is - removed. This is the default.

+ traced processes). Any match specification is + removed. This is the default.

false

Disables tracing for all received messages. - Any match specification is removed.

+ Any match specification is removed.

-

Argument FlagList must be [] - for receive tracing.

-

The return value is always 1.

-

Example; only trace messages from a specific process Pid:

+

Argument FlagList must be [] + for receive tracing.

+

The return value is always 1.

+

Examples:

+

Only trace messages from a specific process Pid:

 > erlang:trace_pattern('receive', [{['_',Pid, '_'],[],[]}], []).
 1
@@ -9522,33 +9720,36 @@ timestamp() ->
 > erlang:trace_pattern('receive', [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).
 1
-

A match specification for 'receive' trace can - use all guard and body functions except caller, - is_seq_trace, get_seq_token, set_seq_token, enable_trace, - disable_trace, trace, silent and process_dump.

+ +

A match specification for 'receive' trace can + use all guard and body functions except caller, + is_seq_trace, get_seq_token, set_seq_token, + enable_trace, disable_trace, trace, + silent, and process_dump.

+
- Sets trace patterns for tracing of function calls. + Set trace patterns for tracing of function calls.

Enables or disables call tracing for one or more functions. - Must be combined with - erlang:trace/3 + Must be combined with + erlang:trace/3 to set the call trace flag - for one or more processes.

+ for one or more processes.

Conceptually, call tracing works as follows. Inside - the Erlang Virtual Machine, a set of processes and + the Erlang virtual machine, a set of processes and a set of functions are to be traced. If a traced process calls a traced function, the trace action is taken. Otherwise, nothing happens.

To add or remove one or more processes to the set of traced processes, use - erlang:trace/3.

+ erlang:trace/3.

To add or remove functions to the set of traced functions, use erlang:trace_pattern/3.

The BIF erlang:trace_pattern/3 can also add match @@ -9560,10 +9761,10 @@ timestamp() -> fails, the action is not executed.

Argument MFA is to be a tuple, such as {Module, Function, Arity}, or the atom on_load - (described in the following). It can be the module, function, + (described below). It can be the module, function, and arity for a function (or a BIF in any module). - The atom '_' can be used as a wild card in any of the - following ways:

+ The atom '_' can be used as a wildcard in any of the + following ways:

{Module,Function,'_'} @@ -9580,7 +9781,7 @@ timestamp() ->

Other combinations, such as {Module,'_',Arity}, are - not allowed. Local functions match wild cards only if + not allowed. Local functions match wildcards only if option local is in FlagList.

If argument MFA is the atom on_load, the match specification and flag list are used on all @@ -9596,13 +9797,14 @@ timestamp() -> true

Enables tracing for the matching functions. - Any match specification is removed.

+ Any match specification is removed.

MatchSpecList

A list of match specifications. An empty list is equivalent to true. For a description of match - specifications, see the User's Guide.

+ specifications, see section + Match Specifications in Erlang in the User's Guide.

restart @@ -9613,7 +9815,7 @@ timestamp() -> pause -

For the FlagList options +

For the FlagList options call_count and call_time: pauses the existing counters. The behavior is undefined for other FlagList options.

@@ -9638,7 +9840,8 @@ timestamp() -> the process, a return_to message is also sent when this function returns to its caller.

- meta | {meta, Pid} | {meta, TracerModule, TracerState} + meta | {meta, Pid} | + {meta, TracerModule, TracerState}

Turns on or off meta-tracing for all types of function @@ -9646,7 +9849,7 @@ timestamp() -> the specified functions are called. If no tracer is specified, self() is used as a default tracer process.

Meta-tracing traces all processes and does not care - about the process trace flags set by trace/3, + about the process trace flags set by erlang:trace/3, the trace flags are instead fixed to [call, timestamp].

The match specification function {return_trace} @@ -9667,7 +9870,8 @@ timestamp() -> Paused and running counters can be restarted from zero with MatchSpec == restart.

To read the counter value, use - erlang:trace_info/2.

+ + erlang:trace_info/2.

call_time @@ -9675,17 +9879,18 @@ timestamp() -> (MatchSpec == false) call time tracing for all types of function calls. For every function, a counter is - incremented when the function is called. + incremented when the function is called. Time spent in the function is accumulated in two other counters, seconds and microseconds. - The counters are stored for each call traced process.

+ The counters are stored for each call traced process.

If call time tracing is started while already running, - the count and time is restarted from zero. To pause + the count and time restart from zero. To pause running counters, use MatchSpec == pause. Paused and running counters can be restarted from zero with MatchSpec == restart.

To read the counter value, use - erlang:trace_info/2.

+ + erlang:trace_info/2.

The options global and local are mutually @@ -9700,12 +9905,12 @@ timestamp() ->

When disabling trace, the option must match the type of trace set on the function. That is, local tracing must be disabled with option local and global tracing with - option global (or no option), and so forth.

+ option global (or no option), and so on.

Part of a match specification list cannot be changed directly. If a function has a match specification, it can be replaced with a new one. To change an existing match specification, use the BIF - erlang:trace_info/2 + erlang:trace_info/2 to retrieve the existing match specification.

Returns the number of functions matching argument MFA. This is zero if none matched.

@@ -9714,7 +9919,7 @@ timestamp() -> - Returns an integer by truncating a number + Return an integer by truncating a number.

Returns an integer by truncating Number, for example:

@@ -9727,7 +9932,7 @@ timestamp() -> - Returns the size of a tuple. + Return the size of a tuple.

Returns an integer that is the number of elements in Tuple, for example:

@@ -9740,11 +9945,11 @@ timestamp() -> - Converts a tuple to a list. + Convert a tuple to a list.

Returns a list corresponding to Tuple. - Tuple can contain any Erlang terms.

-

Example:

+ Tuple can contain any Erlang terms. + Example:

 > tuple_to_list({share, {'Ericsson_B', 163}}).
 [share,{'Ericsson_B',163}]
@@ -9753,112 +9958,110 @@ timestamp() -> - Get a unique integer value + Get a unique integer value. -

Generates and returns an - integer - unique on current runtime system instance. The same as calling - erlang:unique_integer([]).

+

Generates and returns an + + integer unique on current runtime system instance. + The same as calling + + erlang:unique_integer([]).

+ - Get a unique integer value - -

Generates and returns an - integer - unique on current runtime system - instance. The integer is unique in the - sense that this BIF, using the same set of - modifiers, will not return the same integer more - than once on the current runtime system instance. - Each integer value can of course be constructed - by other means.

- -

By default, when [] is passed as - ModifierList, both negative and - positive integers can be returned. This in order - to utilize the range of integers that do - not need heap memory allocation as much as possible. - By default the returned integers are also only - guaranteed to be unique, that is, any returned integer - can be smaller or larger than previously - returned integers.

- -

Valid Modifiers:

- - - positive - -

Return only positive integers.

-

Note that by passing the positive modifier - you will get heap allocated integers (bignums) - quicker.

-
- - monotonic - -

Return - strictly - monotonically increasing integers - corresponding to creation time. That is, the integer - returned will always be larger than previously - returned integers on the current runtime system - instance.

-

These values can be used to determine order between events - on the runtime system instance. That is, if both - X = erlang:unique_integer([monotonic]) and - Y = erlang:unique_integer([monotonic]) are - executed by different processes (or the same - process) on the same runtime system instance and - X < Y we know that X was created - before Y.

-

Strictly monotonically increasing values - are inherently quite expensive to generate and scales - poorly. This is because the values need to be - synchronized between cpu cores. That is, do not pass the monotonic - modifier unless you really need strictly monotonically - increasing values.

-
- -
- -

All valid Modifiers - can be combined. Repeated (valid) - Modifiers in the ModifierList - are ignored.

- -

Note that the set of integers returned by - unique_integer/1 using different sets of - Modifiers will overlap. - For example, by calling unique_integer([monotonic]), - and unique_integer([positive, monotonic]) - repeatedly, you will eventually see some integers being - returned by both calls.

- + Get a unique integer value. + +

Generates and returns an + + integer unique on current runtime system + instance. The integer is unique in the + sense that this BIF, using the same set of + modifiers, does not return the same integer more + than once on the current runtime system instance. + Each integer value can of course be constructed + by other means.

+

By default, when [] is passed as + ModifierList, both negative and + positive integers can be returned. This + to use the range of integers that do + not need heap memory allocation as much as possible. + By default the returned integers are also only + guaranteed to be unique, that is, any returned integer + can be smaller or larger than previously + returned integers.

+

Modifiers:

+ + positive + +

Returns only positive integers.

+

Notice that by passing the positive modifier + you will get heap allocated integers (bignums) quicker.

+
+ monotonic + +

Returns + strictly monotonically increasing integers + corresponding to creation time. That is, the integer + returned is always larger than previously + returned integers on the current runtime system + instance.

+

These values can be used to determine order between events + on the runtime system instance. That is, if both + X = erlang:unique_integer([monotonic]) and + Y = erlang:unique_integer([monotonic]) are + executed by different processes (or the same + process) on the same runtime system instance and + X < Y, we know that X was created + before Y.

+ +

Strictly monotonically increasing values + are inherently quite expensive to generate and scales + poorly. This is because the values need to be synchronized + between CPU cores. That is, do not pass the monotonic + modifier unless you really need strictly monotonically + increasing values.

+
+
+
+

All valid Modifiers + can be combined. Repeated (valid) + Modifiers in the ModifierList + are ignored.

+ +

The set of integers returned by + erlang:unique_integer/1 using different sets of + Modifiers will overlap. + For example, by calling unique_integer([monotonic]), + and unique_integer([positive, monotonic]) + repeatedly, you will eventually see some integers that are + returned by both calls.

+

Failures:

- - badarg - if ModifierList is not a - proper list. - badarg - if Modifier is not a - valid modifier. - + + badarg + if ModifierList is not a + proper list. + badarg + if Modifier is not a + valid modifier. +
- Current date and time according to Universal Time Coordinated (UTC). + Current date and time according to Universal Time Coordinated + (UTC).

Returns the current date and time according to Universal Time Coordinated (UTC) in the form {{Year, Month, Day}, {Hour, Minute, Second}} if supported by the underlying OS. Otherwise erlang:universaltime() is equivalent to - erlang:localtime().

-

Example:

+ erlang:localtime(). Example:

 > erlang:universaltime().
 {{1996,11,6},{14,18,43}}
@@ -9867,15 +10070,15 @@ timestamp() -> - Converts from Universal Time Coordinated (UTC) to local date and time. + Convert from Universal Time Coordinated (UTC) to local date + and time.

Converts Universal Time Coordinated (UTC) date and time to local date and time in the form {{Year, Month, Day}, {Hour, Minute, Second}} if supported by the underlying OS. Otherwise no conversion is done, and - Universaltime is returned.

-

Example:

+ Universaltime is returned. Example:

 > erlang:universaltime_to_localtime({{1996,11,6},{14,18,43}}).
 {{1996,11,7},{15,18,43}}
@@ -9886,7 +10089,7 @@ timestamp() -> - Removes a link to another process or port. + Remove a link to another process or port.

Removes the link, if there is one, between the calling process and the process or port referred to by @@ -9901,8 +10104,8 @@ timestamp() -> in the future (unless the link is setup again). If the caller is trapping exits, an {'EXIT', Id, _} message from the link - can have been placed in the caller's message queue before - the call.

+ can have been placed in the caller's message queue before + the call.

Notice that the {'EXIT', Id, _} message can be the result of the link, but can also be the result of Id @@ -9910,16 +10113,16 @@ timestamp() -> appropriate to clean up the message queue when trapping exits after the call to unlink(Id), as follows:

- unlink(Id), - receive - {'EXIT', Id, _} -> - true - after 0 -> - true - end +unlink(Id), +receive + {'EXIT', Id, _} -> + true +after 0 -> + true +end
-

Prior to OTP release R11B (ERTS version 5.5) unlink/1 - behaved completely asynchronously, i.e., the link was active +

Before Erlang/OTP R11B (ERTS 5.5) unlink/1 + behaved completely asynchronously, that is, the link was active until the "unlink signal" reached the linked entity. This had an undesirable effect, as you could never know when you were guaranteed not to be effected by the link.

@@ -9932,7 +10135,7 @@ timestamp() -> - Removes the registered name for a process (or port). + Remove the registered name for a process (or port).

Removes the registered name RegName associated with a @@ -9948,12 +10151,12 @@ true

- Gets the pid (or port) with a given registered name. + Get the pid (or port) with a specified registered name. +

Returns the process identifier or port identifier with the registered name RegName. Returns undefined - if the name is not registered.

-

Example:

+ if the name is not registered. Example:

 > whereis(db).
 <0.43.0>
@@ -9962,17 +10165,19 @@ true
- Lets other processes get a chance to execute. + Let other processes get a chance to execute.

Voluntarily lets other processes (if any) get a chance to - execute. Using erlang:yield() is similar to + execute. Using this function is similar to receive after 1 -> ok end, except that yield() is faster.

-

There is seldom or never any need to use this BIF, - especially in the SMP emulator, as other processes have a - chance to run in another scheduler thread anyway. - Using this BIF without a thorough grasp of how the scheduler - works can cause performance degradation.

+ +

There is seldom or never any need to use this BIF, + especially in the SMP emulator, as other processes have a + chance to run in another scheduler thread anyway. + Using this BIF without a thorough grasp of how the scheduler + works can cause performance degradation.

+
diff --git a/erts/doc/src/erlc.xml b/erts/doc/src/erlc.xml index a64927fec2..ca3412b72c 100644 --- a/erts/doc/src/erlc.xml +++ b/erts/doc/src/erlc.xml @@ -28,7 +28,7 @@ 1 Bjarne Däcker - 97-03-24 + 1997-03-24 A erlc.xml @@ -38,167 +38,162 @@

The program provides a common way to run all compilers in the Erlang system. Depending on the extension of each input file, - 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.

-

The current working directory, ".", 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).

+ invokes the appropriate compiler. + Regardless of which compiler is used, the same flags are used to provide + parameters, such as include paths and output directory.

+

The current working directory, ".", is not included + in the code path when running the compiler. This to avoid loading + Beam files from the current working directory that could potentially + be in conflict with the compiler or the Erlang/OTP system used by the + compiler.

+ erlc flags file1.ext file2.ext... - Compile files + Compile files. -

compiles one or more files. - The files must include the extension, for example - for Erlang source code, or for Yecc source code. - uses the extension to invoke the correct compiler.

+

Compiles one or more files. The files must include the extension, + for example, for Erlang source code, or + for Yecc source code. + uses the extension to invoke the correct + compiler.

Generally Useful Flags -

The following flags are supported: -

+

The following flags are supported:

- -I directory + -I <Directory>

Instructs the compiler to search for include files in - the specified directory. When encountering an - or directive, the - compiler searches for header files in the following + the Directory. When encountering an + or + directive, the compiler searches for header files in the following directories:

- +

, the current working directory of the - file server;

+ file server

-

the base name of the compiled file;

+

The base name of the compiled file

-

the directories specified using the option. - The directory specified last is searched first.

+

The directories specified using option ; + the directory specified last is searched first

- -o directory + -o <Directory> -

The directory where the compiler should place the output files. - If not specified, output files will be placed in the current working - directory.

+

The directory where the compiler is to place the output files. + Defaults to the current working directory.

- -Dname + -D<Name>

Defines a macro.

- -Dname=value + -D<Name>=<Value> -

Defines a macro with the given value. +

Defines a macro with the specified value. The value can be any Erlang term. Depending on the platform, the value may need to be quoted if the shell itself interprets certain characters. - On Unix, terms which contain tuples and list - must be quoted. Terms which contain spaces + On Unix, terms containing tuples and lists + must be quoted. Terms containing spaces must be quoted on all platforms.

- -Werror + -W<Error>

Makes all warnings into errors.

- -Wnumber + -W<Number> -

Sets warning level to number. Default is . - Use to turn off warnings.

+

Sets warning level to Number. Defaults to + . To turn off warnings, + use .

- -W + -W

Same as . Default.

- -v + -v

Enables verbose output.

- -b output-type + -b <Output_type>

Specifies the type of output file. - Generally, output-type 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 + Output_type is the same as the file extension + of the output file, but without the period. + This option is ignored by compilers that have a single output format.

- -smp + -smp -

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.

+

Compiles using the SMP emulator. This is mainly useful + for compiling native code, which must be compiled with the same + runtime system that it is to be run on.

- -M + -M -

Produces a Makefile rule to track headers dependencies. The - rule is sent to stdout. No object file is produced. -

+

Produces a Makefile rule to track header dependencies. The + rule is sent to stdout. No object file is produced.

- -MF Makefile + -MF <Makefile> -

Like the option above, except that the - Makefile is written to Makefile. No object - file is produced. -

+

As option , except that the + Makefile is written to Makefile. No object + file is produced.

- -MD + -MD -

Same as .Pbeam]]>. -

+

Same as .Pbeam]]>.

- -MT Target + -MT <Target> -

In conjunction with or - , change the name of the rule emitted - to Target. -

+

In conjunction with option or + , changes the name of the rule emitted + to Target.

- -MQ Target + -MQ <Target> -

Like the option above, except that - characters special to make(1) are quoted. -

+

As option , except that characters special to + make/1 are quoted.

- -MP + -MP -

In conjunction with or - , add a phony target for each dependency. -

+

In conjunction with option or + , adds a phony target for each dependency.

- -MG + -MG -

In conjunction with or - , consider missing headers as generated - files and add them to the dependencies. -

+

In conjunction with option or + , considers missing headers as generated + files and adds them to the dependencies.

- -- + --

Signals that no more options will follow. - The rest of the arguments will be treated as file names, + The rest of the arguments is treated as filenames, even if they start with hyphens.

- +term + +<Term> -

A flag starting with a plus ('+') rather than a hyphen - will be converted to an Erlang term and passed unchanged to +

A flag starting with a plus (+) rather than a hyphen + is converted to an Erlang term and passed unchanged to the compiler. - For instance, the option for the Erlang + For example, option for the Erlang compiler can be specified as follows:

 erlc +export_all file.erl

Depending on the platform, the value may need to be quoted if the shell itself interprets certain characters. - On Unix, terms which contain tuples and list - must be quoted. Terms which contain spaces + On Unix, terms containing tuples and lists + must be quoted. Terms containing spaces must be quoted on all platforms.

@@ -206,19 +201,19 @@ erlc +export_all file.erl
Special Flags -

The flags in this section are useful in special situations - such as re-building the OTP system.

+

The following flags are useful in special situations, + such as rebuilding the OTP system:

- -pa directory + -pa <Directory> -

Appends directory to the front of the code path in +

Appends Directory to the front of the code path in the invoked Erlang emulator. This can be used to invoke another compiler than the default one.

- -pz directory + -pz <Directory> -

Appends directory to the code path in +

Appends Directory to the code path in the invoked Erlang emulator.

@@ -226,63 +221,70 @@ erlc +export_all file.erl
Supported Compilers +

The following compilers are supported:

- .erl + .erl

Erlang source code. It generates a file.

-

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.

-

Supported options: -I, -o, -D, -v, -W, -b.

+

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.

+

Supported options: -I, -o, -D, -v, + -W, -b.

- .S + .S -

Erlang assembler source code. It generates a file.

-

Supported options: same as for .erl.

+

Erlang assembler source code. It generates a + file.

+

Supported options: same as for .erl.

- .core + .core -

Erlang core source code. It generates a file.

-

Supported options: same as for .erl.

+

Erlang core source code. It generates a + file.

+

Supported options: same as for .erl.

- .yrl + .yrl

Yecc source code. It generates an file.

-

Use the -I option with the name of a file to use that file - as a customized prologue file (the option).

-

Supported options: -o, -v, -I, -W (see above).

+

Use option -I with the name of a file to use that file + as a customized prologue file (option + ).

+

Supported options: -o, -v, -I, -W.

- .mib + .mib

MIB for SNMP. It generates a file.

-

Supported options: -I, -o, -W.

+

Supported options: -I, -o, -W.

- .bin + .bin -

A compiled MIB for SNMP. It generates a file.

-

Supported options: -o, -v.

+

A compiled MIB for SNMP. It generates a + file.

+

Supported options: -o, -v.

- .rel + .rel

Script file. It generates a boot file.

-

Use the -I to name directories to be searched for application - files (equivalent to the in the option list for - ).

-

Supported options: -o.

+

Use option -I to name directories to be searched for + application files (equivalent to the in the + option list for ).

+

Supported option: -o.

- .asn1 + .asn1 -

ASN1 file.

-

Creates an , , and file from - an file. Also compiles the using the Erlang - compiler unless the options is given.

-

Supported options: -I, -o, -b, -W.

+

ASN1 file. It creates an , + , and file from + an file. Also compiles the + using the Erlang compiler unless option + is specified.

+

Supported options: -I, -o, -b, -W.

- .idl + .idl -

IC file.

-

Runs the IDL compiler.

-

Supported options: -I, -o.

+

IC file. It runs the IDL compiler.

+

Supported options: -I, -o.

@@ -290,20 +292,20 @@ erlc +export_all file.erl
Environment Variables - ERLC_EMULATOR - The command for starting the emulator. - Default is erl in the same directory as the erlc program - itself, or if it doesn't exist, erl in any of the directories - given in the PATH environment variable. + ERLC_EMULATOR + The command for starting the emulator. Defaults to erl + in the same directory as the erlc program itself, + or, if it does not exist, erl in any of the directories + specified in environment variable PATH.
- SEE ALSO -

erl(1), - compile(3), - yecc(3), - snmp(3)

+ See Also +

erl(1), + compiler:compile(3), + parsetools:yecc(3), + snmp:snmp(3)

diff --git a/erts/doc/src/erlsrv.xml b/erts/doc/src/erlsrv.xml index fb00444aa4..53583b625d 100644 --- a/erts/doc/src/erlsrv.xml +++ b/erts/doc/src/erlsrv.xml @@ -28,343 +28,447 @@ - 98-04-29 + 1998-04-29 erlsrv.xml erlsrv - Run the Erlang emulator as a service on Windows NT® + Run the Erlang emulator as a service on Windows -

This utility is specific to Windows NT/2000/XP® (and subsequent versions of Windows) It allows Erlang +

This utility is specific to Windows NT/2000/XP (and later + versions of Windows). It allows Erlang emulators to run as services on the Windows system, allowing embedded - systems to start without any user needing to log in. The + systems to start without any user needing to log on. The emulator started in this way can be manipulated through the - Windows® services applet in a manner similar to other - services.

-

Note that erlsrv is not a general service utility for Windows, but designed for embedded Erlang systems.

-

As well as being the actual service, erlsrv also provides a - command line interface for registering, changing, starting and - stopping services.

-

To manipulate services, the logged in user should have - Administrator privileges on the machine. The Erlang machine + Windows services applet in a manner similar to other services.

+ +

Notice that erlsrv is not a general service utility for Windows, + but designed for embedded Erlang systems.

+ +

erlsrv also provides a command-line interface for registering, + changing, starting, and stopping services.

+ +

To manipulate services, the logged on user is to have + administrator privileges on the machine. The Erlang machine itself is (default) run as the local administrator. This can be - changed with the Services applet in Windows ®.

+ changed with the Services applet in Windows.

+

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.

-

The following parameters may be specified for each Erlang - service:

- + services, be "killed" with the task manager. Killing an emulator + that is started by a service triggers the "OnFail" action + specified for that service, which can be a reboot.

+ +

The following parameters can be specified for each Erlang service:

+ + + -

: This tells how to stop +

Tells how to stop the Erlang emulator. Default is to kill it (Win32 TerminateProcess), but this action can specify any Erlang shell command that will be executed in the emulator to make it stop. The emulator is expected to stop within 30 seconds after the command is issued in the shell. If the emulator is - not stopped, it will report a running state to the service + not stopped, it reports a running state to the service manager.

+ -

: This can be either of , - , or (the - default). In case of , 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. 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.

-

On a system where release handling is - used, this should always be set to . Use - to restart the service on failure instead.

+

Can be one of the following:

+ + + +

The Windows system is rebooted whenever the emulator stops + (a more simple form of watchdog). This can be useful for + less critical systems, otherwise use the heart functionality + to accomplish this.

+
+ + +

Makes the Erlang emulator be + restarted (with whatever parameters are registered for the + service at the occasion) when it stops. If the emulator + stops again within 10 seconds, it is not restarted to avoid + an infinite loop, which could hang the Windows system.

+
+ + +

Similar to , but does + not try to detect cyclic restarts; it is expected that + some other mechanism is present to avoid the problem.

+
+ (the default) + +

Reports the service as stopped to the service manager + whenever it fails; it must be manually restarted.

+
+
+

On a system where release handling is used, + this is always to be set to . Use + to restart the service on failure + instead.

+ -

: The location of the Erlang - emulator. The default is the located in the - same directory as erlsrv.exe. Do not specify - as this emulator, it will not work.

-

If the system - uses release handling, this should be set to a program - similar to .

+

The location of the Erlang emulator. + The default is the located in the same + directory as erlsrv.exe. Do not specify + as this emulator, it will not work.

+

If the system uses release handling, this is to be set to a + program similar to .

+ -

: Specifies an additional environment +

Specifies an extra environment for the emulator. The environment variables specified - here are added to the system wide environment block that is + here are added to the system-wide environment block that is normally present when a service starts up. Variables present - in both the system wide environment and in the service + in both the system-wide environment and in the service environment specification will be set to the value specified in the service.

+ -

: 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 . +

The working directory for the Erlang emulator. + Must be on a local drive (no network drives are mounted when a + service starts). Default working directory for services is + . Debug log files will be placed in this directory.

+ -

: The process priority of the emulator, - this can be one of , , - or (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.

+

The process priority of the emulator. Can be one of the + following:

+ + + +

Not recommended, as the machine will possibly be + inaccessible to interactive users.

+
+ + +

Can be used if two Erlang nodes are to reside on one dedicated + system and one is to have precedence over the other.

+
+ + +

Can be used if interactive performance is not to be affected + by the emulator process.

+
+ (the default> + + +
+ -

: 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.

+

Specifies the short or long + node name of the Erlang emulator. The Erlang services are + always distributed. Default is to use the service name as + (short) nodename.

+ -

: Can be one of (default), - , or . - Specifies that output from the Erlang shell should be +

Specifies that output from the Erlang shell is to be sent to a "debug log". The log file is named <servicename> or - <servicename><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 - option always reuses the same log file - (<servicename>) and the option - uses a separate log file for every invocation of the service - (<servicename><N>). The - option opens an interactive Windows® console window for - the Erlang shell of the service. The option - automatically - disables the and a service started with an - interactive console window will not survive logouts, - actions do not work with debug-consoles either. - If no is specified (), the - output of the Erlang shell is discarded.

-

The is not in any way - intended for production. It is only a convenient way to - debug Erlang services during development. The and - 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 is - intended for debugging only. Logs during production are - better produced with the standard Erlang logging - facilities.

+ <servicename><N>, + where <N> is an integer from 1 through 99. + The log file is placed in the working directory of the + service (as specified in WorkDir).

+

Can be one of the following:

+ + + +

Uses a separate log file for every invocation of the service + (<servicename><N>).

+
+ + +

Reuses the same log file + (<servicename>).

+
+ + +

Opens an interactive Windows console window for the Erlang + shell of the service. Automatically disables the + . A service started with an + interactive console window does not survive logouts. + actions do not work with + debug consoles either.

+
+ (the default) + +

The output of the Erlang shell is discarded.

+
+
+ +

The option is not intended + for production. It is only a convenient way to debug + Erlang services during development.

+

The and options + might seem convenient in a production system, but consider that + the logs grow indefinitely during the system lifetime and cannot + be truncated, except if the service is restarted.

+

In short, the is + intended for debugging only. Logs during production are + better produced with the standard Erlang logging facilities.

+
+ -

: Additional arguments passed to the - emulator startup program (or - ). Arguments that cannot be specified - here are (StopActions would not work), - and (they are specified in any - way. The most common use is for specifying cookies and flags - to be passed to init:boot() ().

+

Passes extra arguments to the emulator startup program + (or ). + Arguments that cannot be specified here are + (StopActions would not work), + , and (they are + specified in any way). The most common use is for specifying cookies + and flags to be passed to init:boot() + ().

+ -

: Specifies the Windows® internal service name (not the display name, which is the one erlsrv uses to identify the service).

-

This internal name can not be changed, it is fixed even if the service is renamed. Erlsrv 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.

-

The internal service name can be seen in the Windows® service manager if viewing Properties for an erlang service.

+

Specifies the Windows-internal service name (not the display name, + which is the one erlsrv uses to identify the service).

+

This internal name cannot be changed, it is fixed even if the + service is renamed. erlsrv generates a unique internal name + when a service is created. It is recommended to keep to the default + if release handling is to be used for the application.

+

The internal service name can be seen in the Windows service + manager if viewing Properties for an Erlang service.

+ -

: A textual comment describing the service. Not mandatory, but shows up as the service description in the Windows® service manager.

+

A textual comment describing the service. Not mandatory, but shows + up as the service description in the Windows service manager.

-
-

- The naming of the service in a system that - uses release handling has to follow the convention + + +

+ The naming of the service in a system that + uses release handling must follow the convention NodeName_Release, where NodeName is - the first part of the Erlang nodename (up to, but not including + the first part of the Erlang node name (up to, but not including the "@") and Release is the current release of the application.

+ erlsrv {set | add} <service-name> [<service options>] - Add or modify an Erlang service + Add or modify an Erlang service. -

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 +

The set and add commands modifies or adds an Erlang + service, respectively. The simplest form of an add command is + without any options in which case all default values (described above) apply. The service name is mandatory.

-

Every option can be given without parameters, in which case - the default value is applied. Values to the options are - supplied only when the default should not be used - (i.e. sets the - default priority and removes all arguments).

-

The following service options are currently available:

+

Every option can be specified without parameters, the + default value is then applied. Values to the options are + supplied only when the default is not to be used. + For example, + sets the default priority and removes all arguments.

+

Service options:

- -st[opaction] [<erlang shell command>] - Defines the StopAction, the command given to the Erlang - shell when the service is stopped. Default is none. - -on[fail] [{reboot | restart | restart_always}] - Specifies the action to take when the Erlang emulator - stops unexpectedly. Default is to ignore. - -m[achine] [<erl-command>] - The complete path to the Erlang emulator, never use the - werl program for this. Default is the in the - same directory as . When release handling - is used, this should be set to a program similar to - . - -e[nv] [<variable>[=<value>]] ... - 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 options can - be specified in one command. Default is to use the system - environment block unmodified (except for two additions, see - below). - -w[orkdir] [<directory>] - The initial working directory of the Erlang - emulator. Default is the system directory. - -p[riority] [{low|high|realtime}] - The priority of the Erlang emulator. The default is the - Windows® default priority. - {-sn[ame] | -n[ame]} [<node-name>] - The node-name of the Erlang machine, distribution is - mandatory. Default is ]]>. + -st[opaction] [<erlang shell command>] + +

Defines the , the command given + to the Erlang shell when the service is stopped. + Default is none.

+
+ -on[fail] [{reboot | restart | restart_always}] + +

The action to take when the Erlang emulator + stops unexpectedly. Default is to ignore.

+
+ -m[achine] [<erl-command>] + +

The complete path to the Erlang emulator. Never use the + werl program for this. Defaults to the + in the same directory as + . When release handling + is used, this is to be set to a program similar to + .

+
+ -e[nv] [<variable>[=<value>]] ... + +

Edits the environment block for the service. Every + environment variable specified is added to the system + environment block. If a variable specified here has the same + name as a system-wide environment variable, the specified + value overrides the system-wide. Environment variables are + added to this list by specifying + <variable>=<value> and deleted from the list by + specifying <variable> alone. The environment block is + automatically sorted. Any number of + options can be specified in one command. Default is to use the + system environment block unmodified (except for two additions, + see section Environment + below).

+
+ -w[orkdir] [<directory>] + +

The initial working directory of the Erlang + emulator. Defaults to the system directory.

+
+ -p[riority] [{low|high|realtime}] + +

The priority of the Erlang emulator. Default to the + Windows default priority.

+
+ {-sn[ame] | -n[ame]} [<node-name>] + +

The node name of the Erlang machine. Distribution is mandatory. + Defaults to ]]>.

+
+ -d[ebugtype] [{new|reuse|console}] + +

Specifies where shell output is to be sent. + Default is that shell output is discarded. + To be used only for debugging.

+
+ -ar[gs] [<limited erl arguments>] + +

Extra arguments to the Erlang emulator. Avoid + , , and + /. Default is + no extra arguments. Remember that the services cookie file is not + necessarily the same as the interactive users. The service + runs as the local administrator. Specify all arguments + together in one string, use double quotes (") to specify an + argument string containing spaces, and use quoted quotes (\") + to specify a quote within the argument string if necessary.

+
+ -i[nternalservicename] [<internal name>] + +

Only allowed for add. 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 + not recommended if release handling is to be + performed. The internal service name cannot be changed once + the service is created. The internal name is not to + be confused with the ordinary service name, which is the name + used to identify a service to erlsrv.

+
+ -c[omment] [<short description>] + +

Specifies a textual comment describing the + service. This comment shows up as the service description + in the Windows service manager.

- -d[ebugtype] [{new|reuse|console}] - Specifies where shell output should be sent, - default is that shell output is discarded. - To be used only for debugging. - -ar[gs] [<limited erl arguments>] - Additional arguments to the Erlang emulator, avoid - , and - /. 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. - -i[nternalservicename] [<internal name>] - Only allowed for add. 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 - not recommended if release handling is to be - performed. The internal service name cannot be changed once - the service is created. The internal name is not to - be confused with the ordinary service name, which is the name - used to identify a service to erlsrv. - -c[omment] [<short description>] - Specifies a textual comment describing the - service. This comment will show upp as the service description - in the Windows® service manager.
+ - erlsrv {start | start_disabled | stop | disable | enable} <service-name> + erlsrv {start | start_disabled | stop | disable | + enable} <service-name> Manipulate the current service status.

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 and + control panels services applet.

+

The and 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.

- -

The start_disabled command operates on a service - regardless of if it's enabled/disabled or started/stopped. It - does this by first enabling it (regardless of if it's enabled - or not), then starting it (if it's not already started) and - then disabling it. The result will be a disabled but started - service, regardless of its earlier state. This is useful for - starting services temporarily during a release upgrade. The - difference between using start_disabled and the - sequence enable, start and disable is - that all other erlsrv commands are locked out during - the sequence of operations in start_disable, making the - operation atomic from an erlsrv user's point of - view.

- + with the service manager for starting and stopping a + service. The commands wait until the service is + started or stopped. When disabling a service, it is not + stopped, the disabled state does not take effect until the + service is stopped. Enabling a service sets it in + automatic mode, which is started at boot. This command cannot + set the service to manual.

+

The start_disabled command operates on a service + regardless of if it is enabled/disabled or started/stopped. It + does this by first enabling it (regardless of if it is enabled + or not), then starting it (if not already started), and + then disabling it. The result is a disabled but started + service, regardless of its earlier state. This is useful for + starting services temporarily during a release upgrade. The + difference between using start_disabled and the + sequence enable, start, and disable is + that all other erlsrv commands are locked out during + the sequence of operations in start_disable, making the + operation atomic from an erlsrv user's point of view.

+ erlsrv remove <service-name> Remove the service. -

This command removes the service completely with all its registered - options. It will be stopped before it is removed.

+

Removes the service completely with all its registered + options. It is stopped before it is removed.

+ erlsrv list [<service-name>] - List all Erlang services or all options for one service. + List all Erlang services or all options for one service. + -

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.

+

If no service name is specified, a brief listing of all Erlang + services is presented. If a service name is supplied, all options + for that service are presented.

+ erlsrv help - Display a brief help text + Display a brief help text. + +

Displays a brief help text.

+
- ENVIRONMENT -

-The environment of an Erlang machine started - as a service will contain two special variables, - , which is the name of the service that - started the machine and which is the - full path to the 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:

+ Environment +

+ The environment of an Erlang machine started + as a service contains two special variables:

+ + + + The name of the service that started the machine. + + The full path to the , which can be + used to manipulate the service. This comes in handy when defining a + heart command for your service. + + +

A command file for restarting a service looks as follows:

+ +

This command file is then set as heart command.

+

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).

+ to the control events generated on logout (see the next section).

- PORT PROGRAMS + Port Programs

When a program runs in - the service context, it has to handle the control events that is + the service context, it must handle the control events that are sent to every program in the system when the interactive user logs off. This is done in different ways for programs running in the console subsystem and programs running as window - applications. An application which runs in the console subsystem + applications. An application running in the console subsystem (normal for port programs) uses the win32 function to register a control handler - that returns TRUE in answer to the + that returns true in answer to the + and events. Other applications - just forward and - to the default window procedure. - Here is a brief example in C of how to set the console control - handler:

+ only forward and + to the default window procedure.

+ +

A brief example in C of how to set the console control handler:

+ /* @@ -383,7 +487,7 @@ void initialize_handler(void){ char buffer[2]; /* * We assume we are running as a service if this - * environment variable is defined + * environment variable is defined. */ if(GetEnvironmentVariable("ERLSRV_SERVICE_NAME",buffer, (DWORD) 2)){ @@ -396,29 +500,34 @@ void initialize_handler(void){
- NOTES -

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.

-

Note that the program resides in the emulators - -directory, not in the -directory directly under + Notes +

Although the options are described in a Unix-like format, the case of + the options or commands is not relevant, and both character "/" and "-" + can be used for options.

+ +

Notice that the program resides in the emulator's + directory, not in the 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.

-

To easily manipulate the Erlang services, put + +

To manipulate the Erlang services easily, put the \erts-\bin]]> directory in - the path instead of \bin]]>. The erlsrv program - can be found from inside Erlang by using the + the path instead of \bin]]>. The + erlsrv program can be found from inside Erlang by using the Erlang function.

-

For release handling to work, use as the Erlang - machine. It is also worth mentioning again that the name of the - service is significant (see above).

+ +

For release handling to work, use as the + Erlang machine. As stated above, + the service name is significant.

- SEE ALSO -

start_erl(1), release_handler(3)

+ See Also +

start_erl(1), + + sasl:release_handler(3)

diff --git a/erts/doc/src/erts_alloc.xml b/erts/doc/src/erts_alloc.xml index 9aef1c0b1f..c1706806fe 100644 --- a/erts/doc/src/erts_alloc.xml +++ b/erts/doc/src/erts_alloc.xml @@ -25,63 +25,68 @@ erts_alloc Rickard Green 1 - 03-06-11 + 2003-06-11 1 erts_alloc.xml erts_alloc - An Erlang Run-Time System internal memory allocator library. + An Erlang runtime system internal memory allocator library. + -

erts_alloc is an Erlang Run-Time System internal memory +

erts_alloc is an Erlang runtime system internal memory allocator library. erts_alloc provides the Erlang - Run-Time System with a number of memory allocators.

+ runtiime system with a number of memory allocators.

Allocators -

Currently the following allocators are present:

+

The following allocators are present:

+ temp_alloc Allocator used for temporary allocations. eheap_alloc - Allocator used for Erlang heap data, such as Erlang process heaps. + Allocator used for Erlang heap data, such as Erlang process heaps. + binary_alloc Allocator used for Erlang binary data. ets_alloc - Allocator used for ETS data. + Allocator used for ets data. driver_alloc Allocator used for driver data. literal_alloc Allocator used for constant terms in Erlang code. sl_alloc Allocator used for memory blocks that are expected to be - short-lived. + short-lived. ll_alloc Allocator used for memory blocks that are expected to be - long-lived, for example Erlang code. + long-lived, for example, Erlang code. fix_alloc A fast allocator used for some frequently used fixed size data types. exec_alloc - Allocator used by hipe for native executable code - on specific architectures (x86_64). + Allocator used by the HiPE + application for native executable code on specific architectures + (x86_64). std_alloc - Allocator used for most memory blocks not allocated via any of - the other allocators described above. + Allocator used for most memory blocks not allocated through any of + the other allocators described above. sys_alloc This is normally the default malloc implementation - used on the specific OS. + used on the specific OS. mseg_alloc - A memory segment allocator. mseg_alloc is used by other - allocators for allocating memory segments and is currently only - available on systems that have the mmap 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. + A memory segment allocator. It is used by other + allocators for allocating memory segments and is only + available on systems that have the mmap system + call. Memory segments that are deallocated are kept for a + while in a segment cache before they are destroyed. When + segments are allocated, cached segments are used if possible + instead of creating new segments. This to reduce + the number of system calls made. +

sys_alloc and literal_alloc are always enabled and cannot be disabled. exec_alloc is only available if it is needed and cannot be disabled. mseg_alloc is always enabled if it is @@ -90,9 +95,10 @@ By default all allocators are enabled. When an allocator is disabled, sys_alloc is used instead of the disabled allocator.

+

The main idea with the erts_alloc library is to separate memory blocks that are used differently into different memory - areas, and by this achieving less memory fragmentation. By + areas, to achieve less memory fragmentation. By putting less effort in finding a good fit for memory blocks that are frequently allocated than for those less frequently allocated, a performance gain can be achieved.

@@ -100,61 +106,85 @@
- The alloc_util framework + The alloc_util Framework

Internally a framework called alloc_util is used for - implementing allocators. sys_alloc, and - mseg_alloc do not use this framework; hence, the + implementing allocators. sys_alloc and + mseg_alloc do not use this framework, so the following does not apply to them.

+

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 mseg_alloc), or in - the heap segment (allocated via sys_alloc). 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 - (sbct) parameter are placed - in singleblock carriers. Blocks that are smaller than the value - of the sbct parameter are placed in multiblock - carriers. Normally an allocator creates a "main multiblock + separate memory segment (allocated through mseg_alloc), or in + the heap segment (allocated through sys_alloc).

+ + + +

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 (sbct) parameter + are placed in singleblock carriers.

+
+ +

Blocks that are smaller than the value of parameter sbct + 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 mmbcs parameter.

+ size of the main multiblock carrier is determined by the value of + parameter mmbcs.

+

Sizes of multiblock carriers - allocated via mseg_alloc are - decided based on the values of the largest multiblock carrier - size (lmbcs), the smallest - multiblock carrier size (smbcs), - and the multiblock carrier growth stages - (mbcgs) parameters. If - nc is the current number of multiblock carriers (the main + allocated through mseg_alloc are decided based on the + following parameters:

+ + + The values of the largest multiblock carrier size + (lmbcs) + The smallest multiblock carrier size + (smbcs) + The multiblock carrier growth stages + (mbcgs) + + +

If nc is the current number of multiblock carriers (the main multiblock carrier excluded) managed by an allocator, the size of the next mseg_alloc multiblock carrier allocated by - this allocator will roughly be + this allocator is roughly when , - and lmbcs when mbcgs]]>. If the value of the - sbct parameter should be larger than the value of the - lmbcs parameter, the allocator may have to create - multiblock carriers that are larger than the value of the - lmbcs parameter, though. - Singleblock carriers allocated via mseg_alloc are sized + and lmbcs when mbcgs]]>. If the value of + parameter sbct is larger than the value of parameter + lmbcs, the allocator may have to create + multiblock carriers that are larger than the value of + parameter lmbcs, though. + Singleblock carriers allocated through mseg_alloc are sized to whole pages.

-

Sizes of carriers allocated via sys_alloc are + +

Sizes of carriers allocated through sys_alloc are decided based on the value of the sys_alloc carrier size - (ycs) parameter. The size of - a carrier is the least number of multiples of the value of the - ycs parameter that satisfies the request.

+ (ycs) parameter. The size of + a carrier is the least number of multiples of the value of + parameter ycs satisfying the request.

+

Coalescing of free blocks are always performed immediately. - Boundary tags (headers and footers) in free blocks are used + Boundary tags (headers and footers) in free blocks are used, which makes the time complexity for coalescing constant.

+

The memory allocation strategy - used for multiblock carriers by an - allocator is configurable via the as - parameter. Currently the following strategies are available:

+ used for multiblock carriers by an allocator can be + configured using parameter as. + The following strategies are available:

+ Best fit -

Strategy: Find the smallest block that satisfies the +

Strategy: Find the smallest block satisfying the requested block size.

Implementation: A balanced binary search tree is used. The time complexity is proportional to log N, where @@ -162,7 +192,7 @@ Address order best fit -

Strategy: Find the smallest block that satisfies the +

Strategy: Find the smallest block satisfying the requested block size. If multiple blocks are found, choose the one with the lowest address.

Implementation: A balanced binary search tree is @@ -171,7 +201,7 @@ Address order first fit -

Strategy: Find the block with the lowest address that satisfies the +

Strategy: Find the block with the lowest address satisfying the requested block size.

Implementation: A balanced binary search tree is used. The time complexity is proportional to log N, where @@ -180,8 +210,8 @@ Address order first fit carrier best fit

Strategy: Find the carrier with the lowest address that - can satisfy the requested block size, then find a block within - that carrier using the "best fit" strategy.

+ can satisfy the requested block size, then find a block within + that carrier using the "best fit" strategy.

Implementation: Balanced binary search trees are used. The time complexity is proportional to log N, where N is the number of free blocks.

@@ -189,8 +219,8 @@ Address order first fit carrier address order best fit

Strategy: Find the carrier with the lowest address that - can satisfy the requested block size, then find a block within - that carrier using the "adress order best fit" strategy.

+ can satisfy the requested block size, then find a block within + that carrier using the "address order best fit" strategy.

Implementation: Balanced binary search trees are used. The time complexity is proportional to log N, where N is the number of free blocks.

@@ -200,12 +230,12 @@

Strategy: Try to find the best fit, but settle for the best fit found during a limited search.

Implementation: The implementation uses segregated free - lists with a maximum block search depth (in each list) in - order to find a good fit fast. When the maximum block - search depth is small (by default 3) this implementation + lists with a maximum block search depth (in each list) + to find a good fit fast. When the maximum block + search depth is small (by default 3), this implementation has a time complexity that is constant. The maximum block - search depth is configurable via the - mbsd parameter.

+ search depth can be configured using parameter + mbsd.

A fit @@ -213,43 +243,47 @@ block to see if it satisfies the request. This strategy is only intended to be used for temporary allocations.

Implementation: Inspect the first block in a free-list. - If it satisfies the request, it is used; otherwise, a new + If it satisfies the request, it is used, otherwise a new carrier is created. The implementation has a time complexity that is constant.

-

As of erts version 5.6.1 the emulator will refuse to - use this strategy on other allocators than temp_alloc. - This since it will only cause problems for other allocators.

+

As from ERTS 5.6.1 the emulator refuses to + use this strategy on other allocators than temp_alloc. + This because it only causes problems for other allocators.

-

Apart from the ordinary allocators described above a number of - pre-allocators are used for some specific data types. These - pre-allocators pre-allocate a fixed amount of memory for certain data - types when the run-time system starts. As long as pre-allocated memory - is available, it will be used. When no pre-allocated memory is - available, memory will be allocated in ordinary allocators. These - pre-allocators are typically much faster than the ordinary allocators, - but can only satisfy a limited amount of requests.

+ +

Apart from the ordinary allocators described above, some + pre-allocators are used for some specific data types. These + pre-allocators pre-allocate a fixed amount of memory for certain data + types when the runtime system starts. As long as pre-allocated memory + is available, it is used. When no pre-allocated memory is + available, memory is allocated in ordinary allocators. These + pre-allocators are typically much faster than the ordinary allocators, + but can only satisfy a limited number of requests.

System Flags Effecting erts_alloc -

Only use these flags if you are absolutely sure what you are - doing. Unsuitable settings may cause serious performance +

Only use these flags if you are sure what you are + doing. Unsuitable settings can cause serious performance degradation and even a system crash at any time during operation.

+

Memory allocator system flags have the following syntax: -

]]> +

]]>, where ]]> is a letter identifying a subsystem, ]]> is a parameter, and ]]> is the value to use. The flags can be passed to the Erlang emulator - (erl) as command line + (erl(1)) as command-line arguments.

-

System flags effecting specific allocators have an upper-case + +

System flags effecting specific allocators have an uppercase letter as ]]>. The following letters are used for - the currently present allocators:

+ the allocators:

+ B: binary_alloc D: std_alloc @@ -265,421 +299,516 @@ X: exec_alloc Y: sys_alloc -

The following flags are available for configuration of - mseg_alloc:

- - ]]> - - 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. - ]]> - - 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. - - - Set super carrier only flag. This - flag defaults to true. When a super carrier is used and this - flag is true, mseg_alloc will only create carriers - in the super carrier. Note that the alloc_util framework may - create sys_alloc carriers, so if you want all carriers to - be created in the super carrier, you therefore want to disable use - of sys_alloc carriers by also passing - +Musac false. When the flag - is false, mseg_alloc will try to create carriers outside - of the super carrier when the super carrier is full. -

- NOTE: Setting this flag to false may not be supported - on all systems. This flag will in that case be ignored. -

- NOTE: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. -
- ]]> - - Set super carrier reserved - free segment descriptors. This parameter defaults to 65536. - This parameter determines the amount of memory to reserve for - free segment descriptors used by the super carrier. If the system - runs out of reserved memory for free segment descriptors, other - memory will be used. This may however cause fragmentation issues, - so you want to ensure that this never happens. The maximum amount - of free segment descriptors used can be retrieved from the - erts_mmap tuple part of the result from calling - erlang:system_info({allocator, mseg_alloc}). - - - - Set super carrier reserve physical - memory flag. This flag defaults to true. When this flag is - true, physical memory will be reserved for the whole super - carrier at once when it is created. The reservation will after that - be left unchanged. When this flag is set to false only virtual - address space will be reserved for the super carrier upon creation. - The system will attempt to reserve physical memory upon carrier - creations in the super carrier, and attempt to unreserve physical - memory upon carrier destructions in the super carrier. -

- NOTE: What reservation of physical memory actually means - highly depends on the operating system, and how it is configured. For - example, different memory overcommit settings on Linux drastically - change the behaviour. Also note, setting this flag to false - may not be supported on all systems. This flag will in that case - be ignored. -

- NOTE: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. -
- ]]> - - Set super carrier size (in MB). The super carrier size defaults to - zero; i.e, the super carrier is by default disabled. The super - carrier is a large continuous area in the virtual address space. - mseg_alloc will always try to create new carriers in the super - carrier if it exists. Note that the alloc_util framework may - create sys_alloc carriers. For more information on this, see the - documentation of the +MMsco - flag. -

- NOTE: The super carrier cannot be enabled nor - disabled on halfword heap systems. This flag will be - ignored on halfword heap systems. -
- ]]> - - Max cached segments. The maximum number of memory segments - stored in the memory segment cache. Valid range is - 0-30. Default value is 10. -
-

The following flags are available for configuration of - sys_alloc:

- - +MYe true - - Enable sys_alloc. Note: sys_alloc cannot be disabled. - +MYm libc - - malloc library to use. Currently only - libc is available. libc enables the standard - libc malloc implementation. By default libc is used. - ]]> - - Trim threshold size (in kilobytes). This is the maximum amount - of free memory at the top of the heap (allocated by - sbrk) that will be kept by malloc (not - released to the operating system). When the amount of free - memory at the top of the heap exceeds the trim threshold, - malloc will release it (by calling - sbrk). Trim threshold is given in kilobytes. Default - trim threshold is 128. Note: This flag will - only have any effect when the emulator has been linked with - the GNU C library, and uses its malloc implementation. - ]]> - - Top pad size (in kilobytes). This is the amount of extra - memory that will be allocated by malloc when - sbrk is called to get more memory from the operating - system. Default top pad size is 0. Note: This flag - will only have any effect when the emulator has been linked - with the GNU C library, and uses its malloc - implementation. - -

The following flags are available for configuration of allocators - based on alloc_util. If u is used as subsystem - identifier (i.e., = u]]>) all allocators based on - alloc_util will be effected. If B, D, E, - F, H, L, R, S, or T is used as - subsystem identifier, only the specific allocator identified will be - effected:

- - acul |de]]> - - Abandon carrier utilization limit. A valid - ]]> is an integer in the range - [0, 100] representing utilization in percent. When a - utilization value larger than zero is used, allocator instances - are allowed to abandon multiblock carriers. If de (default - enabled) is passed instead of a ]]>, - a recomended non zero utilization value will be used. The actual - value chosen depend on allocator type and may be changed between - ERTS versions. Currently the default equals de, but this - may be changed in the future. Carriers will be abandoned when - memory utilization in the allocator instance falls below the - utilization value used. Once a carrier has been abandoned, no new - allocations will be made in it. When an allocator instance gets an - increased multiblock carrier need, it will first try to fetch an - abandoned carrier from an allocator instances of the same - allocator type. If no abandoned carrier could be fetched, it will - create a new empty carrier. When an abandoned carrier has been - fetched it will function as an ordinary carrier. This feature has - special requirements on the - allocation strategy used. Currently - only the strategies aoff, aoffcbf and aoffcaobf support - abandoned carriers. This feature also requires - multiple thread specific instances - to be enabled. When enabling this feature, multiple thread specific - instances will be enabled if not already enabled, and the - aoffcbf strategy will be enabled if current strategy does not - support abandoned carriers. This feature can be enabled on all - allocators based on the alloc_util framework with the - exception of temp_alloc (which would be pointless). - - as bf|aobf|aoff|aoffcbf|aoffcaobf|gf|af]]> - - Allocation strategy. Valid strategies are bf (best fit), - aobf (address order best fit), aoff (address order first fit), - aoffcbf (address order first fit carrier best fit), - aoffcaobf (address order first fit carrier address order best fit), - gf (good fit), and af (a fit). See - the description of allocation strategies in "the alloc_util framework" section. - asbcst ]]> - - Absolute singleblock carrier shrink threshold (in - kilobytes). When a block located in an - mseg_alloc 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 rsbcst. - e true|false]]> - - Enable allocator ]]>. - lmbcs ]]> - - Largest (mseg_alloc) multiblock carrier size (in - kilobytes). See the description - on how sizes for mseg_alloc multiblock carriers are decided - in "the alloc_util framework" section. On 32-bit Unix style OS - this limit can not be set higher than 128 megabyte. - mbcgs ]]> - - (mseg_alloc) multiblock carrier growth stages. See - the description on how sizes for - mseg_alloc multiblock carriers are decided - in "the alloc_util framework" section. - mbsd ]]> - - Max block search depth. This flag has effect only if the - good fit strategy has been selected for allocator - ]]>. 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. - mmbcs ]]> - - Main multiblock carrier size. Sets the size of the main - multiblock carrier for allocator ]]>. The main - multiblock carrier is allocated via and is - never deallocated. - mmmbc ]]> - - Max mseg_alloc multiblock carriers. Maximum number of - multiblock carriers allocated via mseg_alloc by - allocator ]]>. When this limit has been reached, - new multiblock carriers will be allocated via - sys_alloc. - mmsbc ]]> - - Max mseg_alloc singleblock carriers. Maximum number of - singleblock carriers allocated via mseg_alloc by - allocator ]]>. When this limit has been reached, - new singleblock carriers will be allocated via - sys_alloc. - ramv ]]> - - 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. - - rmbcmt ]]> - - 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. - rsbcmt ]]> - - 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 - sbct 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. - rsbcst ]]> - - Relative singleblock carrier shrink threshold (in - percent). When a block located in an mseg_alloc - 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 asbcst. - sbct ]]> - - Singleblock carrier threshold. Blocks larger than this - threshold will be placed in singleblock carriers. Blocks - smaller than this threshold will be placed in multiblock - carriers. On 32-bit Unix style OS this threshold can not be set higher - than 8 megabytes. - smbcs ]]> - - Smallest (mseg_alloc) multiblock carrier size (in - kilobytes). See the description - on how sizes for mseg_alloc multiblock carriers are decided - in "the alloc_util framework" section. - t true|false]]> - -

Multiple, thread specific instances of the allocator. - This option will only have any effect on the runtime system - with SMP support. Default behaviour on the runtime system with - SMP support is NoSchedulers+1 instances. Each scheduler will use - a lock-free instance of its own and other threads will use - a common instance.

-

It was previously (before ERTS version 5.9) possible to configure - a smaller amount of thread specific instances than schedulers. - This is, however, not possible any more.

-
-
-

Currently the following flags are available for configuration of - alloc_util, i.e. all allocators based on alloc_util - will be effected:

- - ]]> - - sys_alloc carrier size. Carriers allocated via - sys_alloc will be allocated in sizes which are - multiples of the sys_alloc carrier size. This is not - true for main multiblock carriers and carriers allocated - during a memory shortage, though. - ]]> - - Max mseg_alloc 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 - sys_alloc. - ]]> - - Allow sys_alloc carriers. By default true. If - set to false, sys_alloc carriers will never be - created by allocators using the alloc_util framework. - -

The following flag is special for literal_alloc:

- - ]]> - - literal_alloc super carrier size (in MB). The amount of - virtual address space reserved for literal terms in - Erlang code on 64-bit architectures. The default is 1024 (1GB) - and is usually sufficient. The flag is ignored on 32-bit - architectures. - -

The following flag is special for exec_alloc:

- - ]]> - - exec_alloc super carrier size (in MB). The amount of - virtual address space reserved for native executable code - used by hipe on specific architectures (x86_64). The default is 512 MB. - - -

Instrumentation flags:

- - +Mim true|false - - A map over current allocations is kept by the emulator. The - allocation map can be retrieved via the instrument - module. +Mim true implies +Mis true. - +Mim true is the same as - -instr. - +Mis true|false - - Status over allocated memory is kept by the emulator. The - allocation status can be retrieved via the instrument - module. - +Mit X - - Reserved for future use. Do not use this flag. - - -

When instrumentation of the emulator is enabled, the emulator - uses more memory and runs slower.

-
-

Other flags:

- - +Mea min|max|r9c|r10b|r11b|config - + +
+ Flags for Configuration of mseg_alloc + + ]]> + +

Absolute maximum cache bad fit (in kilobytes). A segment in the + memory segment cache is not reused if its size exceeds the + requested size with more than the value of this + parameter. Defaults to 4096.

+
+ ]]> + +

Relative maximum cache bad fit (in percent). A segment in the + memory segment cache is not reused if its size exceeds the + requested size with more than relative maximum cache bad fit + percent of the requested size. Defaults to 20.

+
+ + +

Sets super carrier only flag. + Defaults to true. When a super carrier is used and this + flag is true, mseg_alloc only creates carriers in + the super carrier. Notice that the alloc_util framework can + create sys_alloc carriers, so if you want all carriers to + be created in the super carrier, you therefore want to disable use + of sys_alloc carriers by also passing + +Musac false. When + the flag is false, mseg_alloc tries to create carriers + outside of the super carrier when the super carrier is full.

+ +

Setting this flag to false is possibly not supported + on all systems. The flag is then ignored.

+
+ +

The super carrier cannot be enabled or + disabled on halfword heap systems. This flag is + ignored on halfword heap systems.

+
+
+ ]]> + +

Sets super carrier reserved + free segment descriptors. Defaults to 65536. + This parameter determines the amount of memory to reserve for + free segment descriptors used by the super carrier. If the system + runs out of reserved memory for free segment descriptors, other + memory is used. This can however cause fragmentation issues, + so you want to ensure that this never happens. The maximum amount + of free segment descriptors used can be retrieved from the + erts_mmap tuple part of the result from calling + + erlang:system_info({allocator, mseg_alloc}).

+
+ + +

Sets super carrier reserve + physical memory flag. Defaults to true. When this flag is + true, physical memory is reserved for the whole super + carrier at once when it is created. The reservation is after that + left unchanged. When this flag is set to false, only virtual + address space is reserved for the super carrier upon creation. + The system attempts to reserve physical memory upon carrier + creations in the super carrier, and attempt to unreserve physical + memory upon carrier destructions in the super carrier.

+ +

What reservation of physical memory means, highly + depends on the operating system, and how it is configured. For + example, different memory overcommit settings on Linux drastically + change the behavior.

+

Setting this flag to false is possibly not supported on + all systems. The flag is then ignored.

+
+ +

The super carrier cannot be enabled or + disabled on halfword heap systems. This flag is + ignored on halfword heap systems.

+
+
+ ]]> + +

Sets super carrier size (in MB). Defaults to 0, that is, + the super carrier is by default disabled. The super + carrier is a large continuous area in the virtual address space. + mseg_alloc always tries to create new carriers in the super + carrier if it exists. Notice that the alloc_util framework + can create sys_alloc carriers. For more information, see + +MMsco.

+ +

The super carrier cannot be enabled or + disabled on halfword heap systems. This flag is + ignored on halfword heap systems.

+
+
+ ]]> + +

Maximum cached segments. The maximum number of memory segments + stored in the memory segment cache. Valid range is [0, 30]. + Defaults to 10.

+
+
+
+ +
+ Flags for Configuration of sys_alloc + + +MYe true + +

Enables sys_alloc.

+ +

sys_alloc cannot be disabled.

+
+
+ +MYm libc + +

malloc library to use. Only + libc is available. libc enables the standard + libc malloc implementation. By default libc + is used.

+
+ ]]> + +

Trim threshold size (in kilobytes). This is the maximum amount + of free memory at the top of the heap (allocated by + sbrk) that is kept by malloc (not + released to the operating system). When the amount of free + memory at the top of the heap exceeds the trim threshold, + malloc releases it (by calling sbrk). + Trim threshold is specified in kilobytes. + Defaults to 128.

+ +

This flag has effect only when the emulator is linked with + the GNU C library, and uses its malloc implementation.

+
+
+ ]]> + +

Top pad size (in kilobytes). This is the amount of extra + memory that is allocated by malloc when + sbrk is called to get more memory from the operating + system. Defaults to 0.

+ +

This flag has effect only when the emulator is linked with + the GNU C library, and uses its malloc implementation.

+
+
+
+
+ +
+ Flags for Configuration of Allocators Based on alloc_util +

If u is used as subsystem identifier (that is, + = u]]>), all allocators based on + alloc_util are effected. If B, D, E, + F, H, L, R, S, or T is used + as subsystem identifier, only the specific allocator identifier is + effected.

+ + + acul |de]]> + + +

Abandon carrier utilization limit. A valid + ]]> is an integer in the range + [0, 100] representing utilization in percent. When a + utilization value > 0 is used, allocator instances + are allowed to abandon multiblock carriers. If de (default + enabled) is passed instead of a ]]>, + a recomended non-zero utilization value is used. The value + chosen depends on the allocator type and can be changed between + ERTS versions. Defaults to de, but this + can be changed in the future.

+

Carriers are abandoned when + memory utilization in the allocator instance falls below the + utilization value used. Once a carrier is abandoned, no new + allocations are made in it. When an allocator instance gets an + increased multiblock carrier need, it first tries to fetch an + abandoned carrier from an allocator instances of the same + allocator type. If no abandoned carrier can be fetched, it + creates a new empty carrier. When an abandoned carrier has been + fetched, it will function as an ordinary carrier. This feature has + special requirements on the + allocation strategy used. Only + the strategies aoff, aoffcbf, and aoffcaobf + support abandoned carriers.

+

This feature also requires + multiple thread specific instances + to be enabled. When enabling this feature, multiple thread-specific + instances are enabled if not already enabled, and the + aoffcbf strategy is enabled if the current strategy does not + support abandoned carriers. This feature can be enabled on all + allocators based on the alloc_util framework, except + temp_alloc (which would be pointless).

+
+ + as bf|aobf|aoff|aoffcbf|aoffcaobf|gf|af]]> + +

Allocation strategy. The following strategies are valid:

+ + bf (best fit) + aobf (address order best fit) + aoff (address order first fit) + aoffcbf (address order first fit carrier best fit) + + aoffcaobf (address order first fit carrier address + order best fit) + gf (good fit) + af (a fit) + +

See the description of allocation strategies in section + The alloc_util Framework.

+
+ asbcst ]]> + +

Absolute singleblock carrier shrink threshold (in + kilobytes). When a block located in an + mseg_alloc singleblock carrier is shrunk, the carrier + is left unchanged if the amount of unused memory is less + than this threshold, otherwise the carrier is shrunk. + See also rsbcst.

+
+ e true|false]]> + +

Enables allocator ]]>.

+
+ lmbcs ]]> + +

Largest (mseg_alloc) multiblock carrier size (in kilobytes). + See the description on how sizes for mseg_alloc multiblock + carriers are decided in section + + The alloc_util Framework. On + 32-bit Unix style OS this limit cannot be set > 128 MB.

+
+ mbcgs ]]> + +

(mseg_alloc) multiblock carrier growth stages. + See the description on how sizes for mseg_alloc multiblock + carriers are decided in section + + The alloc_util Framework.

+
+ mbsd ]]> + +

Maximum block search depth. This flag has effect only if the + good fit strategy is selected for allocator + ]]>. When the good fit strategy is used, free + blocks are placed in segregated free-lists. Each free-list + contains blocks of sizes in a specific range. The maxiumum block + search depth sets a limit on the maximum number of blocks to + inspect in a free-list during a search for suitable block + satisfying the request.

+
+ mmbcs ]]> + +

Main multiblock carrier size. Sets the size of the main + multiblock carrier for allocator ]]>. The main + multiblock carrier is allocated through + and is never deallocated.

+
+ mmmbc ]]> + +

Maximum mseg_alloc multiblock carriers. Maximum number of + multiblock carriers allocated through mseg_alloc by + allocator ]]>. When this limit is reached, + new multiblock carriers are allocated through + sys_alloc.

+
+ mmsbc ]]> + +

Maximum mseg_alloc singleblock carriers. Maximum number of + singleblock carriers allocated through mseg_alloc by + allocator ]]>. When this limit is reached, + new singleblock carriers are allocated through + sys_alloc.

+
+ ramv ]]> + +

Realloc always moves. When enabled, reallocate operations are + more or less translated into an allocate, copy, free sequence. + This often reduces memory fragmentation, but costs performance.

+
+ rmbcmt ]]> + +

Relative multiblock carrier move threshold (in percent). When + a block located in a multiblock carrier is shrunk, + the block is moved if the ratio of the size of the returned + memory compared to the previous size is more than this threshold, + otherwise the block is shrunk at the current location.

+
+ rsbcmt ]]> + +

Relative singleblock carrier move threshold (in percent). When + a block located in a singleblock carrier is shrunk to + a size smaller than the value of parameter + sbct, + the block is left unchanged in the singleblock carrier if + the ratio of unused memory is less than this threshold, + otherwise it is moved into a multiblock carrier.

+
+ rsbcst ]]> + +

Relative singleblock carrier shrink threshold (in + percent). When a block located in an mseg_alloc + singleblock carrier is shrunk, the carrier is left + unchanged if the ratio of unused memory is less than this + threshold, otherwise the carrier is shrunk. + See also asbcst.

+
+ sbct ]]> + +

Singleblock carrier threshold. Blocks larger than this + threshold are placed in singleblock carriers. Blocks + smaller than this threshold are placed in multiblock + carriers. On 32-bit Unix style OS this threshold cannot be set + > 8 MB.

+
+ smbcs ]]> + +

Smallest (mseg_alloc) multiblock carrier size (in + kilobytes). See the description on how sizes for mseg_alloc + multiblock carriers are decided in section + + The alloc_util Framework.

+
+ t true|false]]> + +

Multiple, thread-specific instances of the allocator. + This option has only effect on the runtime system + with SMP support. Default behavior on the runtime system with + SMP support is NoSchedulers+1 instances. Each scheduler + uses a lock-free instance of its own and other threads use + a common instance.

+

Before ERTS 5.9 it was possible to configure + a smaller number of thread-specific instances than schedulers. + This is, however, not possible anymore.

+
+
+
+ +
+ Flags for Configuration of alloc_util +

All allocators based on alloc_util are effected.

+ + + ]]> + +

sys_alloc carrier size. Carriers allocated through + sys_alloc are allocated in sizes that are + multiples of the sys_alloc carrier size. This is not + true for main multiblock carriers and carriers allocated + during a memory shortage, though.

+
+ ]]> + +

Maximum mseg_alloc carriers. Maximum number of carriers + placed in separate memory segments. When this limit is + reached, new carriers are placed in memory retrieved from + sys_alloc.

+
+ ]]> + +

Allow sys_alloc carriers. Defaults to true. + If set to false, sys_alloc carriers are never + created by allocators using the alloc_util framework.

+
+
+
+ +
+ Special Flag for literal_alloc - min + ]]> - Disables all allocators that can be disabled. - +

literal_alloc super carrier size (in MB). The amount of + virtual address space reserved for literal terms in + Erlang code on 64-bit architectures. Defaults to 1024 + (that is, 1 GB), which is usually sufficient. + The flag is ignored on 32-bit architectures.

+ +
+
- max +
+ Special Flag for exec_alloc + + ]]> - Enables all allocators (currently default). - +

exec_alloc super carrier size (in MB). The amount of + virtual address space reserved for native executable code + used by the HiPE application + on specific architectures (x86_64). Defaults to 512.

+ +
+
- r9c|r10b|r11b +
+ Instrumentation Flags + + +Mim true|false - Configures all allocators as they were configured in respective - OTP release. These will eventually be removed. - +

A map over current allocations is kept by the emulator. + The allocation map can be retrieved through module + + tools:instrument(3). +Mim true + implies +Mis true. +Mim true is the same as flag + -instr in + erl(1).

+ + +Mis true|false + +

Status over allocated memory is kept by the emulator. + The allocation status can be retrieved through module + + tools:instrument(3).

+
+ +Mit X + +

Reserved for future use. Do not use this flag.

+
+
- config + +

When instrumentation of the emulator is enabled, the emulator + uses more memory and runs slower.

+
+
+ +
+ Other Flags + + +Mea min|max|r9c|r10b|r11b|config + +

Options:

+ + min + +

Disables all allocators that can be disabled.

+
+ max + +

Enables all allocators (default).

+
+ r9c|r10b|r11b + +

Configures all allocators as they were configured in respective + Erlang/OTP release. These will eventually be removed.

+
+ config + +

Disables features that cannot be enabled while creating an + allocator configuration with + + runtime_tools:erts_alloc_config(3).

+ +

This option is to be used only while running + runtime_tools:erts_alloc_config(3), not when + using the created configuration.

+
+
+
+
+ +Mlpm all|no - Disables features that cannot be enabled while creating an - allocator configuration with - erts_alloc_config(3). - Note, this option should only be used while running - erts_alloc_config, not when using the created - configuration. +

Lock physical memory. Defaults to no, that is, + no physical memory is locked. If set to all, all + memory mappings made by the runtime system are locked into + physical memory. If set to all, the runtime system fails to + start if this feature is not supported, the user has not got enough + privileges, or the user is not allowed to lock enough physical + memory. The runtime system also fails with an out of memory + condition if the user limit on the amount of locked memory is + reached.

- - +Mlpm all|no - Lock physical memory. The default value is no, i.e., - no physical memory will be locked. If set to all, all - memory mappings made by the runtime system, will be locked into - physical memory. If set to all, the runtime system will fail - to start if this feature is not supported, the user has not got enough - privileges, or the user is not allowed to lock enough physical memory. - The runtime system will also fail with an out of memory condition - if the user limit on the amount of locked memory is reached. - - -

Only some default values have been presented - here. - erlang:system_info(allocator), - and - erlang:system_info({allocator, Alloc}) - can be used in order to obtain currently used settings and current - status of the allocators.

+
+
+ +
+ Notes +

Only some default values have been presented here. For information + about the currently used settings and the current status of the + allocators, see + + erlang:system_info(allocator) and + + erlang:system_info({allocator, Alloc}).

+ -

Most of these flags are highly implementation dependent, and they - may be changed or removed without prior notice.

+

Most of these flags are highly implementation-dependent and + can be changed or removed without prior notice.

erts_alloc is not obliged to strictly use the settings that - have been passed to it (it may even ignore them).

+ have been passed to it (it can even ignore them).

-

erts_alloc_config(3) - is a tool that can be used to aid creation of an + +

The + runtime_tools:erts_alloc_config(3) + tool can be used to aid creation of an erts_alloc configuration that is suitable for a limited number of runtime scenarios.

- SEE ALSO -

erts_alloc_config(3), - erl(1), - instrument(3), - erlang(3)

+ See Also +

erl(1), + erlang(3), + + runtime_tools:erts_alloc_config(3), + + tools:instrument(3)

diff --git a/erts/doc/src/escript.xml b/erts/doc/src/escript.xml index f12f76890c..602b88f6ed 100644 --- a/erts/doc/src/escript.xml +++ b/erts/doc/src/escript.xml @@ -33,17 +33,18 @@ Erlang scripting support

escript provides support for running short Erlang programs - without having to compile them first and an easy way to retrieve the - command line arguments.

+ without having to compile them first, and an easy way to retrieve the + command-line arguments.

+ script-name script-arg1 script-arg2... escript escript-flags script-name script-arg1 script-arg2... - Run a script written in Erlang + Run a script written in Erlang.

escript runs a script written in Erlang.

-

Here follows an example.

+

Example:

 $ chmod u+x factorial
 $ cat factorial
@@ -73,195 +74,183 @@ factorial 5 = 120
 $ ./factorial
 usage: factorial integer
 $ ./factorial five
-usage: factorial integer
-        
+usage: factorial integer

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 escript. However if you - invoke the escript like this

+ a normal Erlang module. The first line is intended to be the + interpreter line, which invokes escript.

+

However, if you invoke the escript as follows, + the contents of the first line does not matter, but it + cannot contain Erlang code as it will be ignored:

-$ escript factorial 5        
-

the contents of the first line does not matter, but it - cannot contain Erlang code as it will be ignored.

-

The second line in the example, contains an optional - directive to the Emacs editor which causes it to +$ escript factorial 5 +

The second line in the example contains an optional + directive to the Emacs editor, which causes it to enter the major mode for editing Erlang source files. If the - directive is present it must be located on the second + directive is present, it must be located on the second line.

- -

If there is a comment selecting the encoding it can be +

If a comment selecting the encoding exists, it can be located on the second line.

- -

- The encoding specified by the above mentioned comment - applies to the script itself. The encoding of the - I/O-server, however, has to be set explicitly like this:

-io:setopts([{encoding, unicode}]) + +

The encoding specified by the above mentioned comment + applies to the script itself. The encoding of the + I/O-server, however, must be set explicitly as follows:

+ +io:setopts([{encoding, unicode}])

The default encoding of the I/O-server for standard_io - is latin1 - since the script runs in a non-interactive terminal - (see - Using Unicode in Erlang). -

- -

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

+ is latin1, as the script runs in a non-interactive terminal + (see section + + Summary of Options) in the STDLIB User's Guide.

+
+

On the third line (or second line depending on the presence + of the Emacs directive), arguments can be specified to + the emulator, for example:

 %%! -smp enable -sname factorial -mnesia debug verbose

Such an argument line must start with %%! and the - rest of the line will interpreted as arguments to the emulator.

+ remaining line is interpreted as arguments to the emulator.

If you know the location of the escript executable, the first - line can directly give the path to escript. For instance:

+ line can directly give the path to escript, for example:

-#!/usr/local/bin/escript        
-

As any other kind of scripts, Erlang scripts will not work on +#!/usr/local/bin/escript +

As any other type of scripts, Erlang scripts do not work on Unix platforms if the execution bit for the script file is not set. - (Use chmod +x script-name to turn on the execution bit.) -

- -

The rest of the Erlang script file may either contain - Erlang source code, an inlined beam file or an - inlined archive file.

- -

An Erlang script file must always contain the function - main/1. When the script is run, the - main/1 function will be called with a list - of strings representing the arguments given to the script (not - changed or interpreted in any way).

- + (To turn on the execution bit, use chmod +x script-name.)

+

The remaining Erlang script file can either contain + Erlang source code, an inlined beam file, or an + inlined archive file.

+

An Erlang script file must always contain the main/1 + function. When the script is run, the + main/1 function is called with a list + of strings representing the arguments specified to the script (not + changed or interpreted in any way).

If the main/1 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.

- -

To return your own non-zero exit code, call halt(ExitCode); - for instance:

+ the exit status for the script is 0. If an exception is + generated during execution, a short message is printed and the script + terminates with exit status 127.

+

To return your own non-zero exit code, call halt(ExitCode), + for example:

 halt(1).
- -

Call escript:script_name() - from your to script to retrieve the pathname of the script - (the pathname is usually, but not always, absolute).

- +

To retrieve the pathname of the script, call + + escript:script_name() from your script + (the pathname is usually, but not always, absolute).

If the file contains source code (as in the example above), - it will be processed by the preprocessor epp. This - means that you for example may use pre-defined macros (such as - ?MODULE) as well as include directives like - the -include_lib directive. For instance, use

+ it is processed by the + epp preprocessor. + This means that you, for example, can use predefined macros + (such as ?MODULE) and include directives like + the -include_lib directive. For example, use

 -include_lib("kernel/include/file.hrl").
-

to include the record definitions for the records used by the - file:read_link_info/1 function. You can also select - encoding by including a encoding comment here, but if there - is a valid encoding comment on the second line it takes +

to include the record definitions for the records used by function + + file:read_link_info/1. You can also select + encoding by including an encoding comment here, but if + a valid encoding comment exists on the second line, it takes precedence.

- -

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.

- +

The script is checked for syntactic and semantic + correctness before it is run. If there are warnings (such as + unused variables), they are printed and the script will + still be run. If there are errors, they are printed and + the script will not be run and its exit status is + 127.

Both the module declaration and the export declaration of the main/1 function are optional.

-

By default, the script will be interpreted. You can force it to be compiled by including the following line somewhere - in the script file:

+          in the script file:

+
 -mode(compile).
-

Execution of interpreted code is slower than compiled code. - If much of the execution takes place in interpreted code it - may be worthwhile to compile it, even though the compilation - itself will take a little while. It is also possible to supply - native instead of compile, this will compile the script - using the native flag, again depending on the characteristics - of the escript this could or could not be worth while.

- -

As mentioned earlier, it is possible to have a script which + If much of the execution takes place in interpreted code, it + can be worthwhile to compile it, although the compilation + itself takes a little while. Also, native can be supplied + instead of compile. This compiles the script + using the native flag and may or may not be worthwhile + depending on the escript characteristics.

+

As mentioned earlier, a script can contains precompiled beam code. In a precompiled - script, the interpretation of the script header is exactly - the same as in a script containing source code. That means + script, the interpretation of the script header is + the same as in a script containing source code. This means that you can make a beam file executable by prepending the file with the lines starting with #! and %%! mentioned above. In a precompiled script, the - function - main/1 must be exported.

- -

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 + main/1 function must be exported.

+

Another option is to have an entire + Erlang archive in the script. In an archive script, the + interpretation of the script header is the same as + in a script containing source code. This means that you can make an archive file executable by prepending the file with the lines starting with #! and %%! mentioned - above. In an archive script, the function main/1 must + above. In an archive script, the main/1 function must be exported. By default the main/1 function in the module with the same name as the basename of the - escript file will be invoked. This behavior can be - overridden by setting the flag -escript main Module - as one of the emulator flags. The Module must be the - name of a module which has an exported main/1 - function. See code(3) - for more information about archives and code loading.

- -

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:

-
+          escript file is invoked. This behavior can be
+          overridden by setting flag -escript main Module
+          as one of the emulator flags. Module must be the
+          name of a module that has an exported main/1
+          function. For more information about archives and code loading, see
+          kernel:code(3).

+

It is often very convenient to have a header in + the escript, especially on Unix platforms. However, the header + is optional, so you directly can "execute" + an Erlang module, Beam file, or archive file without adding + any header to them. But then you have to invoke the script + as follows:

+
 $ escript factorial.erl 5
 factorial 5 = 120
 $ escript factorial.beam 5
 factorial 5 = 120
 $ escript factorial.zip 5
-factorial 5 = 120
-
+factorial 5 = 120
+ - escript:create(FileOrBin, Sections) -> ok | {ok, binary()} | {error, term()} - Create an escript + escript:create(FileOrBin, Sections) -> ok | {ok, binary()} | + {error, term()} + Create an escript. FileOrBin = filename() | 'binary' Sections = [Header] Body | Body Header = shebang | {shebang, Shebang} - | comment | {comment, Comment} - | {emu_args, EmuArgs} +    | comment | {comment, Comment} +    | {emu_args, EmuArgs} Shebang = string() | 'default' | 'undefined' Comment = string() | 'default' | 'undefined' EmuArgs = string() | 'undefined' - Body = {source, SourceCode} - | {beam, BeamCode} - | {archive, ZipArchive} - | {archive, ZipFiles, ZipOptions} + Body = {source, SourceCode} | {beam, BeamCode} +    | {archive, ZipArchive} +    | {archive, ZipFiles, ZipOptions} SourceCode = BeamCode = file:filename() | binary() - ZipArchive = zip:filename() | binary() + ZipArchive = + zip:filename() | binary() ZipFiles = [ZipFile] - ZipFile = file:filename() | {file:filename(), binary()} | {file:filename(), binary(), file:file_info()} - ZipOptions = [zip:create_option()] + ZipFile = file:filename() +    | {file:filename(), binary()} +    | {file:filename(), binary(), file:file_info()} + ZipOptions = [ + zip:create_option()] -

The create/2 - function creates an escript from a list of sections. The - sections can be given in any order. An escript begins with an - optional Header followed by a mandatory Body. If - the header is present, it does always begin with a - shebang, possibly followed by a comment and - emu_args. The shebang defaults to - "/usr/bin/env escript". The comment defaults to - "This is an -*- erlang -*- file". The created escript - can either be returned as a binary or written to file.

- -

As an example of how the function can be used, we create an - interpreted escript which uses emu_args to set some emulator - flag. In this case it happens to disable the smp_support. We - do also extract the different sections from the newly created - script:

+

+ Creates an escript from a list of sections. The + sections can be specified in any order. An escript begins with an + optional Header followed by a mandatory Body. If + the header is present, it does always begin with a + shebang, possibly followed by a comment and + emu_args. The shebang defaults to + "/usr/bin/env escript". The comment defaults to + "This is an -*- erlang -*- file". The created escript + can either be returned as a binary or written to file.

+

As an example of how the function can be used, we create an + interpreted escript that uses emu_args to set some emulator + flag. In this case, it happens to disable the smp_support. We + also extract the different sections from the newly created script:

 > Source = "%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_support)).\n".
 "%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_support)).\n"
@@ -280,11 +269,9 @@ ok
 "false"
 > escript:extract("demo.escript", []).
 {ok,[{shebang,default}, {comment,default}, {emu_args,"-smp disable"},
-     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_su"...>>}]}
-	
- -

An escript without header can be created like this:

-
+     {source,<<"%% Demo\nmain(_Args) ->\n    io:format(erlang:system_info(smp_su"...>>}]}
+

An escript without header can be created as follows:

+
 > file:write_file("demo.erl",
                   ["%% demo.erl\n-module(demo).\n-export([main/1]).\n\n", Source]).
 ok
@@ -299,14 +286,12 @@ ok
      {beam,<<70,79,82,49,0,0,3,68,66,69,65,77,65,116,
              111,109,0,0,0,83,0,0,0,9,...>>}]}
 > os:cmd("escript demo.beam").
-"true"
-
-

Here we create an archive script containing both Erlang - code as well as beam code. Then we iterate over all files in - the archive and collect their contents and some info about - them. -

-
+"true"
+

Here we create an archive script containing both Erlang + code and Beam code, then we iterate over all files in + the archive and collect their contents and some information about + them:

+
 > {ok, SourceCode} = file:read_file("demo.erl").
 {ok,<<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}
 > escript:create("demo.escript",
@@ -339,43 +324,43 @@ ok
       <<"%% demo.erl\n-module(demo).\n-export([main/1]).\n\n%% Demo\nmain(_Arg"...>>}]}
+ - escript:extract(File, Options) -> {ok, Sections} | {error, term()} - Parses an escript and extracts its sections + escript:extract(File, Options) -> {ok, Sections} | + {error, term()} + Parse an escript and extract its sections. File = filename() Options = [] | [compile_source] Sections = Headers Body Headers = {shebang, Shebang} - {comment, Comment} - {emu_args, EmuArgs} + {comment, Comment} + {emu_args, EmuArgs} Shebang = string() | 'default' | 'undefined' Comment = string() | 'default' | 'undefined' EmuArgs = string() | 'undefined' Body = {source, SourceCode} - | {source, BeamCode} - | {beam, BeamCode} - | {archive, ZipArchive} +    | {source, BeamCode} +    | {beam, BeamCode} +    | {archive, ZipArchive} SourceCode = BeamCode = ZipArchive = binary() -

The extract/2 - function parses an escript and extracts its sections. This is - the reverse of create/2.

- -

All sections are returned even if they do not exist in the - escript. If a particular section happens to have the same - value as the default value, the extracted value is set to the - atom default. If a section is missing, the extracted - value is set to the atom undefined.

- -

The compile_source option only affects the result if - the escript contains source code. In that case the - Erlang code is automatically compiled and {source, - BeamCode} is returned instead of {source, - SourceCode}.

- -
+        

+ Parses an escript and extracts its sections. This is the reverse + of create/2.

+

All sections are returned even if they do not exist in the + escript. If a particular section happens to have the same + value as the default value, the extracted value is set to the + atom default. If a section is missing, the extracted + value is set to the atom undefined.

+

Option compile_source only affects the result if + the escript contains source code. In this case the + Erlang code is automatically compiled and {source, + BeamCode} is returned instead of {source, + SourceCode}.

+

Example:

+
 > escript:create("demo.escript",
                  [shebang, {archive, [{"demo.erl", SourceCode},
                                       {"demo.beam", BeamCode}], []}]).
@@ -385,52 +370,51 @@ ok
               escript:extract("demo.escript", []).
 {ok,[{{archive,<<80,75,3,4,20,0,0,0,8,0,118,7,98,60,105,
                 152,61,93,107,0,0,0,118,0,...>>}
-     {emu_args,undefined}]}
-	
+ {emu_args,undefined}]}
+ escript:script_name() -> File - Returns the name of an escript + Return the name of an escript. File = filename() -

The - script_name/0 function returns the name of the escript - being executed. If the function is invoked outside the context - of an escript, the behavior is undefined.

+

+ Returns the name of the escript that is executed. + If the function is invoked outside the context + of an escript, the behavior is undefined.

- Options accepted by escript + Options Accepted By escript - -c - Compile the escript regardless of the value of the mode attribute. + -c + Compiles the escript regardless of the value of the mode attribute. - - -d - Debug the escript. Starts the debugger, loads the module - containing the main/1 function into the debugger, sets a - breakpoint in main/1 and invokes main/1. If the - module is precompiled, it must be explicitly compiled with the - debug_info option. + -d + Debugs the escript. Starts the debugger, loads the module + containing the main/1 function into the debugger, sets a + breakpoint in main/1, and invokes main/1. If the + module is precompiled, it must be explicitly compiled with option + debug_info. - - -i - Interpret the escript regardless of the value of the mode attribute. + -i + Interprets the escript regardless of the value of the mode + attribute. + + -s + Performs a syntactic and semantic check of the script file. + Warnings and errors (if any) are written to the standard output, but + the script will not be run. The exit status is 0 if any errors + are found, otherwise 127. + + -n + Compiles the escript using flag +native. - - -s - 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. - - -n - Compile the escript using the +native flag.
diff --git a/erts/doc/src/inet_cfg.xml b/erts/doc/src/inet_cfg.xml index 027fe600d7..37653a08e9 100644 --- a/erts/doc/src/inet_cfg.xml +++ b/erts/doc/src/inet_cfg.xml @@ -22,7 +22,7 @@ - Inet configuration + Inet Configuration Peter Andersson 2004-03-02 @@ -32,374 +32,341 @@
Introduction -

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.

-

When Erlang starts up it will read the kernel variable - which, if defined, should specify the location and - name of a user configuration file. Example:

-

-

Note that the usage of a file, which was - supported in earlier Erlang versions, is now obsolete.

-

A second way to specify the configuration file is to set the - environment variable to the full name of the file. Example (bash):

-

-

Note that the kernel variable overrides this environment variable.

+

This section describes how the Erlang runtime system is configured + for IP communication. It also explains how you can configure it + for your needs by a configuration file. + The information is primarily intended for users with special + configuration needs or problems. There is normally no need + for specific settings for Erlang to function properly on a correctly + IP-configured platform.

+ +

When Erlang starts up it reads the Kernel variable + , which, if defined, is to specify the location + and name of a user configuration file. Example:

+ + + +

Notice that the use of an file, which was + supported in earlier Erlang/OTP versions, is now obsolete.

+ +

A second way to specify the configuration file is to set + environment variable to the full name of + the file. Example (bash):

+ + + +

Notice that the Kernel variable + overrides this environment variable.

+

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 - inet_res.

+ in non-distributed or short name distributed mode, Erlang uses + default configuration settings and a native lookup method that + works correctly under most circumstances. Erlang reads no + information from system inet configuration files (such as + /etc/host.conf and /etc/nsswitch.conf) 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 + kernel:inet_res.

+

If Erlang is started in long name distributed mode, it needs to - get the domain name from somewhere and will read system inet + get the domain name from somewhere and reads system 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 found is also recorded, but not + used as long as Erlang is configured for native lookups. The information becomes useful if the lookup method is changed to - or , see below).

-

Native lookup (system calls) is always the default resolver method. This - is true for all platforms except VxWorks and OSE Delta where - or is used (in that order of priority).

-

On Windows platforms, Erlang will search the system registry rather than - look for configuration files when started in long name distributed mode.

+ or , see below.

+ +

Native lookup (system calls) is always the default resolver method. + This is true for all platforms, except VxWorks and OSE Delta where + or is used (in that + priority order).

+ +

On Windows platforms, Erlang searches the system registry rather than + looks for configuration files when started in long name distributed + mode.

Configuration Data

Erlang records the following data in a local database if found in system - inet configuration files (or system registry):

- - Host names and addresses + inet configuration files (or system registry):

+ + + Hostnames and host addresses Domain name Nameservers Search domains Lookup method -

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 + +

This data can also be specified explicitly in the user + configuration file. This file is to contain lines + of configuration parameters (each terminated with a full stop). + Some parameters add data to the configuration (such as host and nameserver), others overwrite any previous settings - (e.g. domain and lookup). The user configuration file is always + (such as domain and lookup). The user configuration file is always examined last in the configuration process, making it possible for the user to override any default values or previously made settings. Call to view the state of the - inet configuration database.

-

These are the valid configuration parameters:

-

+ inet configuration database.

+ +

The valid configuration parameters are as follows:

+ - + -

-

-

Specify a system file that Erlang should read configuration - data from. tells the parser how the file should be - interpreted: (Unix resolv.conf), - (FreeBSD host.conf), (BSDOS host.conf), - (Linux host.conf), - (Unix nsswitch.conf) or (Unix hosts). should - specify the name of the file with full path.

-

+

Specify a system file that Erlang is to read configuration data from. + tells the parser how the file is to be + interpreted:

+ + (Unix resolv.conf) + (FreeBSD host.conf) + (BSDOS host.conf) + (Linux host.conf) + (Unix nsswitch.conf) + (Unix hosts) + +

is to specify the filename with full + path.

- + -

-

-

Specify a system file that Erlang should read resolver +

Specify a system file that Erlang is to read resolver configuration from for the internal DNS client - inet_res, + kernel:inet_res, and monitor for changes, even if it does not exist. The path must be absolute.

-

This may override the configuration parameters +

This can override the configuration parameters and depending on the contents - of the specified file. They may also change any time in the future + of the specified file. They can also change any time in the future reflecting the file contents.

-

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 +

If the file is specified as an empty string "", + no file is read or monitored in the future. This emulates + the old behavior of not configuring the DNS client when the node is started in short name distributed mode.

-

If this parameter is not specified it defaults to - unless the environment variable - is set which defines +

If this parameter is not specified, it defaults to + unless environment variable + is set, which defines the directory for this file to some maybe other than .

-

- + -

-

-

Specify a system file that Erlang should read resolver - configuration from for the internal hosts file resolver +

Specify a system file that Erlang is to read resolver + configuration from for the internal hosts file resolver, and monitor for changes, even if it does not exist. The path must be absolute.

These host entries are searched after all added with {file, hosts, File} above or - {host, IP, Aliases} below when the lookup option + {host, IP, Aliases} below when lookup option file is used.

-

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 +

If the file is specified as an empty string "", + no file is read or monitored in the future. This emulates + the old behavior of not configuring the DNS client when the node is started in short name distributed mode.

-

If this parameter is not specified it defaults to - unless the environment variable - is set which defines +

If this parameter is not specified, it defaults to + unless environment variable + is set, which defines the directory for this file to some maybe other than .

-

- + -

-

-

Specify a system registry that Erlang should read configuration - data from. Currently, is the only valid option.

-

+

Specify a system registry that Erlang is to read configuration + data from. is the only valid option.

- + -

-

Add host entry to the hosts table.

-

- + -

-

Set domain name.

-

- + -

-

-

Add address (and port, if other than default) of primary +

Add address (and port, if other than default) of the primary nameserver to use for - inet_res.

-

+ kernel:inet_res. +

- + -

-

-

Add address (and port, if other than default) of secondary +

Add address (and port, if other than default) of the secondary nameserver for - inet_res.

-

+ kernel:inet_res. +

- + -

-

Add search domains for - inet_res.

-

+ kernel:inet_res. +

- + -

-

-

Specify lookup methods and in which order to try them. - The valid methods are: (use system calls), - (use host data retrieved from - system configuration files and/or - the user configuration file) or - (use the Erlang DNS client - inet_res - for nameserver queries).

+

Specify lookup methods and in which order to try them. + The valid methods are as follows:

+ + (use system calls) + (use host data retrieved from system + configuration files and/or the user configuration file) + (use the Erlang DNS client + kernel:inet_res + for nameserver queries) +

The lookup method tries to - parse the hostname as a IPv4 or IPv6 string and return + parse the hostname as an IPv4 or IPv6 string and return the resulting IP address. It is automatically tried first when is not - in the list. To skip it in this case + in the list. To skip it in this case, the pseudo lookup method can be inserted anywhere in the list.

-

- + -

-

-

Set size of resolver cache. Default is 100 DNS records.

-

+

Set the resolver cache size. Defaults to 100 DNS records.

- - -

+ +

-

-

Set how often (in millisec) - the resolver cache for - inet_res. - is refreshed (i.e. expired DNS records are deleted). - Default is 1 h.

-

+

Set how often (in milliseconds) the resolver cache for + kernel:inet_res + is refreshed (that is, expired DNS records are deleted). + Defaults to 1 hour.

- + -

-

-

Set the time to wait until retry (in millisec) for DNS queries +

Set the time to wait until retry (in milliseconds) for DNS queries made by - inet_res. - Default is 2 sec.

-

+ kernel;inet_res. + Defaults to 2 seconds.

- + -

-

Set the number of DNS queries - inet_res - will try before giving up. - Default is 3.

-

+ kernel:inet_res + will try before giving up. Defaults to 3.

- + -

-

-

Tells the DNS client - inet_res - to look up IPv6 addresses. Default is false.

-

+

Tells the DNS client + kernel:inet_res + to look up IPv6 addresses. Defaults to false.

- + -

-

-

Tells the DNS client - inet_res - to use TCP (Virtual Circuit) instead of UDP. Default is false.

-

+

Tells the DNS client + kernel:inet_res + to use TCP (Virtual Circuit) instead of UDP. Defaults to + false.

- + -

-

Sets the EDNS version that - inet_res - will use. The only allowed is zero. Default is false - which means to not use EDNS.

-

+ kernel:inet_res + will use. The only allowed version is zero. Defaults to false, + which means not to use EDNS.

- + -

-

Sets the allowed UDP payload size - inet_res + kernel:inet_res will advertise in EDNS queries. Also sets the limit when the DNS query will be deemed too large for UDP - forcing a TCP query instead, which is not entirely - correct since the advertised UDP payload size of the - individual nameserver is what should be used, + forcing a TCP query instead; this is not entirely + correct, as the advertised UDP payload size of the + individual nameserver is what is to be used, but this simple strategy will do until a more intelligent - (probing, caching) algorithm need be implemented. - The default is 1280 which stems from the - standard Ethernet MTU size.

-

+ (probing, caching) algorithm needs to be implemented. + Default to 1280, which stems from the standard Ethernet MTU size.

- + -

-

-

Tell Erlang to use other primitive UDP module than inet_udp.

-

+

Tell Erlang to use another primitive UDP module than + inet_udp.

- + -

-

-

Tell Erlang to use other primitive TCP module than inet_tcp.

-

+

Tell Erlang to use another primitive TCP module than + inet_tcp.

- + -

Clear the hosts table.

-

- + -

Clear the list of recorded nameservers (primary and secondary).

-

- + -

Clear the list of search domains.

-

User Configuration Example -

Here follows a user configuration example.

-

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 +

Assume that a user does not want Erlang to use the native lookup method, + but wants Erlang to read all information necessary from start and use + that for resolving names and addresses. If lookup fails, Erlang + is to request the data from a nameserver (using the Erlang DNS client, set to use EDNS allowing larger responses). - The resolver configuration will be updated when - its configuration file changes, furthermore, DNS records - should never be cached. The user configuration file + The resolver configuration is updated when + its configuration file changes. Also, DNS records + are never to be cached. The user configuration file (in this example named , stored - in directory ) could then look like this + in directory ) can then look as follows (Unix):

+
-      %% -- 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]}.
-

And Erlang could, for example, be started like this:

-

+%% -- 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]}.
+ +

And Erlang can, for example, be started as follows:

+ +
diff --git a/erts/doc/src/init.xml b/erts/doc/src/init.xml index a88a815ef6..54507c6572 100644 --- a/erts/doc/src/init.xml +++ b/erts/doc/src/init.xml @@ -19,7 +19,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - + init @@ -30,128 +30,140 @@ init.xml init - Coordination of System Startup + Coordination of system startup. -

The init module is pre-loaded and contains the code for - the init system process which coordinates the start-up of - the system. The first function evaluated at start-up is - boot(BootArgs), where BootArgs is a list of command - line arguments supplied to the Erlang runtime system from - the local operating system. See - erl(1).

-

init reads the boot script which contains instructions on - how to initiate the system. See - script(4) for more - information about boot scripts.

+

This module is preloaded and contains the code for + the init system process that coordinates the startup of + the system. The first function evaluated at startup is + boot(BootArgs), where BootArgs is a list of + command-line arguments supplied to the Erlang runtime system from + the local operating system; see + erl(1).

+ +

init reads the boot script, which contains instructions on + how to initiate the system. For more information about boot scripts, see + sasl:script(4).

+

init also contains functions to restart, reboot, and stop the system.

+ - Start the Erlang runtime system + Start the Erlang runtime system.

Starts the Erlang runtime system. This function is called - when the emulator is started and coordinates system start-up.

-

BootArgs are all command line arguments except - the emulator flags, that is, flags and plain arguments. See - erl(1).

-

init itself interprets some of the flags, see - Command Line Flags below. + when the emulator is started and coordinates system startup.

+

BootArgs are all command-line arguments except + the emulator flags, that is, flags and plain arguments; see + erl(1).

+

init interprets some of the flags, see section + Command-Line Flags below. The remaining flags ("user flags") and plain arguments are passed to the init loop and can be retrieved by calling - get_arguments/0 and get_plain_arguments/0, - respectively.

+ get_arguments/0 + and + get_plain_arguments/0, respectively.

+ - Get the values associated with a command line user flag + Get the values associated with a command-line user flag. + -

Returns all values associated with the command line user flag - Flag. If Flag is provided several times, each - Values is returned in preserved order.

+

Returns all values associated with the command-line user flag + Flag. If Flag is provided + several times, each Values is returned in + preserved order. Example:

 % erl -a b c -a d
 ...
 1> init:get_argument(a).
 {ok,[["b","c"],["d"]]}
-

There are also a number of flags, which are defined +

The following flags are defined automatically and can be retrieved using this function:

root -

The installation directory of Erlang/OTP, $ROOT.

+

The installation directory of Erlang/OTP, $ROOT:

 2> init:get_argument(root).
 {ok,[["/usr/local/otp/releases/otp_beam_solaris8_r10b_patched"]]}
progname -

The name of the program which started Erlang.

+

The name of the program which started Erlang:

 3> init:get_argument(progname).
 {ok,[["erl"]]}
home -

The home directory.

+

The home directory:

 4> init:get_argument(home).
 {ok,[["/home/harry"]]}
-

Returns error if there is no value associated with - Flag.

+

Returns error if no value is associated with Flag.

+ - Get all command line user flags + Get all command-line user flags. -

Returns all command line flags, as well as the system - defined flags, see get_argument/1.

+

Returns all command-line flags and the system-defined flags, see + get_argument/1.

+ - Get all non-flag command line arguments + Get all non-flag command-line arguments. -

Returns any plain command line arguments as a list of strings +

Returns any plain command-line arguments as a list of strings (possibly empty).

+ - Get system status information + Get system status information.

The current status of the init process can be inspected. During system startup (initialization), InternalStatus is starting, and - ProvidedStatus indicates how far the boot script has - been interpreted. Each {progress, Info} term - interpreted in the boot script affects ProvidedStatus, - that is, ProvidedStatus gets the value of Info.

+ ProvidedStatus indicates how far the boot + script has been interpreted. Each {progress, Info} term + interpreted in the boot script affects + ProvidedStatus, that is, + ProvidedStatus gets the value of Info.

+ - Take down and restart an Erlang node smoothly + Take down and restart an Erlang node smoothly.

All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system - terminates. If the -heart command line flag was given, - the heart program will try to reboot the system. Refer - to heart(3) for more information.

+ terminates. If command-line flag -heart was specified, + the heart program tries to reboot the system. For more + information, see + kernel:heart(3).

To limit the shutdown time, the time init is allowed - to spend taking down applications, the -shutdown_time - command line flag should be used.

+ to spend taking down applications, command-line flag + -shutdown_time is to be used.

+ - Restart the running Erlang node + Restart the running Erlang node.

The system is restarted inside the running Erlang node, which means that the emulator is not restarted. All @@ -160,80 +172,91 @@ the same way as initially started. The same BootArgs are used again.

To limit the shutdown time, the time init is allowed - to spend taking down applications, the -shutdown_time - command line flag should be used.

+ to spend taking down applications, command-line flag + -shutdown_time is to be used.

+ - Get the identity of the used boot script + Get the identity of the used boot script. -

Get the identity of the boot script used to boot the system. +

Gets the identity of the boot script used to boot the system. Id can be any Erlang term. In the delivered boot - scripts, Id is {Name, Vsn}. Name and - Vsn are strings.

+ scripts, Id is {Name, Vsn}. Name + and Vsn are strings.

+ - Take down an Erlang node smoothly + Take down an Erlang node smoothly.

The same as stop(0).

+ - Take down an Erlang node smoothly + Take down an Erlang node smoothly.

All applications are taken down smoothly, all code is unloaded, and all ports are closed before the system - terminates by calling halt(Status). If the - -heart command line flag was given, the heart - program is terminated before the Erlang node - terminates. Refer to heart(3) for more - information.

+ terminates by calling halt(Status). If + command-line flag -heart was specified, the heart + program is terminated before the Erlang node terminates. + For more information, see + kernel:heart(3).

To limit the shutdown time, the time init is allowed - to spend taking down applications, the -shutdown_time - command line flag should be used.

+ to spend taking down applications, command-line flag + -shutdown_time is to be used.

- Command Line Flags -

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 - -code_path_choice flag is also experimental.

+ Command-Line Flags + +

The support for loading of code from archive files is + experimental. The only purpose of releasing it before it is ready + is to obtain early feedback. The file format, semantics, + interfaces, and so on, can be changed in a future release. The + -code_path_choice flag is also experimental.

+
-

The init module interprets the following command line - flags:

+

The init module interprets the following command-line flags:

--

Everything following -- up to the next flag is considered plain arguments and can be retrieved using - get_plain_arguments/0.

+ + get_plain_arguments/0.

-code_path_choice Choice -

This flag can be set to strict or relaxed. It - controls whether each directory in the code path should be - interpreted strictly as it appears in the boot script or if - init 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 boot script. See script(4) for more information - about interpretation of boot scripts. The flag does also have - a similar affect on how the code server works. See code(3).

- +

Can be set to strict or relaxed. It controls how each + directory in the code path is to be interpreted:

+ + +

Strictly as it appears in the boot script, or

+
+ +

init is to 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 boot script. For more + information about interpretation of boot scripts, see + sasl:script(4). + The flag has also a similar effect on how the code server works; see + kernel:code(3).

-epmd_module Module @@ -242,11 +265,11 @@ -eval Expr -

Scans, parses and evaluates an arbitrary expression +

Scans, parses, and evaluates an arbitrary expression Expr 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 uses Erlang as a hexadecimal calculator:

+ steps fail (syntax error, parse error, or exception during + evaluation), Erlang stops with an error message. In the following + example Erlang is used as a hexadecimal calculator:

 % erl -noshell -eval 'R = 16#1F+16#A0, io:format("~.16B~n", [R])' \\
 -s erlang halt
@@ -256,14 +279,15 @@ BF
-eval expressions are evaluated sequentially with -s and -run function calls (this also in the order specified). As with -s and -run, an - evaluation that does not terminate, blocks the system + evaluation that does not terminate blocks the system initialization process.

-extra

Everything following -extra is considered plain arguments and can be retrieved using - get_plain_arguments/0.

+ + get_plain_arguments/0.

-run Mod [Func [Arg1, Arg2, ...]] @@ -285,8 +309,8 @@ foo:bar() foo:bar(["baz", "1", "2"]).

The functions are executed sequentially in an initialization process, which then terminates normally and passes control to - the user. This means that a -run call which does not - return will block further processing; to avoid this, use + the user. This means that a -run call that does not + return blocks further processing; to avoid this, use some variant of spawn in such cases.

-s Mod [Func [Arg1, Arg2, ...]] @@ -309,11 +333,11 @@ foo:bar() foo:bar([baz, '1', '2']).

The functions are executed sequentially in an initialization process, which then terminates normally and passes control to - the user. This means that a -s call which does not - return will block further processing; to avoid this, use + the user. This means that a -s call that does not + return blocks further processing; to avoid this, use some variant of spawn in such cases.

-

Due to the limited length of atoms, it is recommended that - -run be used instead.

+

Because of the limited length of atoms, it is recommended to + use -run instead.

@@ -335,9 +359,9 @@ error
- SEE ALSO -

erl_prim_loader(3), - heart(3)

+ See Also +

erl_prim_loader(3), + kernel:heart(3)

diff --git a/erts/doc/src/introduction.xml b/erts/doc/src/introduction.xml new file mode 100644 index 0000000000..97a0d5999e --- /dev/null +++ b/erts/doc/src/introduction.xml @@ -0,0 +1,56 @@ + + + + +
+ + 20122016 + Ericsson AB. All Rights Reserved. + + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + + + Introduction + + + + + + 2016-05-22 + PA1 + introduction.xml +
+
+ Scope +

The Erlang Runtime System Application, ERTS, contains + functionality necessary to run the Erlang system.

+ +

By default, is only guaranteed to be + compatible with other Erlang/OTP components from the same release as + itself.

+

For information on how to communicate with Erlang/OTP components + from earlier releases, see the documentation of system flag + +R in erl(1). +

+
+
+ +
+ Prerequisites +

It is assumed that the reader is familiar with the Erlang programming + language.

+
+
+ diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml index 7be3d15de6..ee50815fde 100644 --- a/erts/doc/src/match_spec.xml +++ b/erts/doc/src/match_spec.xml @@ -22,7 +22,7 @@ - Match specifications in Erlang + Match Specifications in Erlang Patrik Nyblom @@ -32,43 +32,54 @@ PA1 match_spec.xml -

A "match specification" (match_spec) is an Erlang term describing a - small "program" that will try to match something. It can be used +

A "match specification" (match_spec) is an Erlang term describing a + small "program" that tries to match something. It can be used to either control tracing with erlang:trace_pattern/3 or to search for objects in an ETS table with for example ets:select/2. - 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 + The match specification in many ways works like a small function in Erlang, + but is interpreted/compiled by the Erlang runtime system to something much more + efficient than calling an Erlang function. The match specification is also very limited compared to the expressiveness of real Erlang functions.

-

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., ) in the - part, - which resembles an Erlang guard, will generate immediate failure, - while an exception in the part, which resembles the body of an - Erlang function, is implicitly caught and results in the single atom - . -

+

The most notable difference between a match specification and an Erlang + fun is the syntax. Match specifications are Erlang terms, not Erlang code. + Also, a match specification has a strange concept of exceptions:

+ + + +

An exception (such as ) in the + part, which resembles an Erlang guard, + generates immediate failure.

+
+ +

An exception in the part, which resembles + the body of an Erlang function, is implicitly caught and results in the + single atom .

+
+
Grammar -

A match_spec used in tracing can be described in this informal grammar:

+

A match specification used in tracing can be described in the following + informal grammar:

+ MatchExpression ::= [ MatchFunction, ... ] MatchFunction ::= { MatchHead, MatchConditions, MatchBody } - MatchHead ::= MatchVariable | | [ MatchHeadPart, ... ] + MatchHead ::= MatchVariable | | + [ MatchHeadPart, ... ] + + MatchHeadPart ::= term() | MatchVariable | - MatchHeadPart ::= term() | MatchVariable | MatchVariable ::= '$<number>' - MatchConditions ::= [ MatchCondition, ...] | - MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + MatchConditions ::= [ MatchCondition, ...] | + + MatchCondition ::= { GuardFunction } | { GuardFunction, + ConditionExpression, ... } BoolFunction ::= | | | @@ -79,58 +90,77 @@ | | | | | | - | | - + | | + + ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct + + ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | + | - ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - | TermConstruct = {{}} | {{ ConditionExpression, ... }} | | [ConditionExpression, ...] | | #{term() => ConditionExpression, ...} | - NonCompositeTerm | Constant - NonCompositeTerm ::= term() (not list or tuple or map) + NonCompositeTerm | Constant + + NonCompositeTerm ::= term() (not list or tuple or map) + Constant ::= {, term()} GuardFunction ::= BoolFunction | | - | | | | - | | | | - | | | | - | | | | - | | | ']]> | - =']]> | | | | - | | | | - + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ']]> | + =']]> | | + | | + | | + | | + + MatchBody ::= [ ActionTerm ] ActionTerm ::= ConditionExpression | ActionCall - ActionCall ::= {ActionFunction} | - {ActionFunction, ActionTerm, ...} + ActionCall ::= {ActionFunction} | {ActionFunction, ActionTerm, ...} ActionFunction ::= | - | | - | | | - | | | - | | | - + | | + | | + | | + | | + | | + | + -

A match_spec used in ets can be described in this informal grammar:

+

A match specification used in + stdlib:ets + can be described in the following informal grammar:

+ MatchExpression ::= [ MatchFunction, ... ] MatchFunction ::= { MatchHead, MatchConditions, MatchBody } - MatchHead ::= MatchVariable | | { MatchHeadPart, ... } + MatchHead ::= MatchVariable | | + { MatchHeadPart, ... } + + MatchHeadPart ::= term() | MatchVariable | - MatchHeadPart ::= term() | MatchVariable | MatchVariable ::= '$<number>' - MatchConditions ::= [ MatchCondition, ...] | + MatchConditions ::= [ MatchCondition, ...] | + MatchCondition ::= { GuardFunction } | - { GuardFunction, ConditionExpression, ... } + { GuardFunction, ConditionExpression, ... } BoolFunction ::= | | | @@ -141,243 +171,324 @@ | | | | | | - | | - + | | + + ConditionExpression ::= ExprMatchVariable | { GuardFunction } | - { GuardFunction, ConditionExpression, ... } | TermConstruct + { GuardFunction, ConditionExpression, ... } | TermConstruct ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | - | + | + TermConstruct = {{}} | {{ ConditionExpression, ... }} | | [ConditionExpression, ...] | #{} | - #{term() => ConditionExpression, ...} | NonCompositeTerm | - Constant - NonCompositeTerm ::= term() (not list or tuple or map) + #{term() => ConditionExpression, ...} | NonCompositeTerm | Constant + + NonCompositeTerm ::= term() (not list or tuple or map) + Constant ::= {, term()} GuardFunction ::= BoolFunction | | - | | | | - | | | | - | | | | - | | | | - | | | ']]> | - =']]> | | | | - | | | | - - MatchBody ::= [ ConditionExpression, ... ] + | | + | | + | | + | | + | | + | | + | | + | | + | | + | ']]> | + =']]> | | + | | + | | + | | + + + MatchBody ::= [ ConditionExpression, ... ] +
- Function descriptions - + Function Descriptions
- Functions allowed in all types of match specifications -

The different functions allowed in work like this: -

-

is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, - is_reference, is_tuple, is_map, is_binary, is_function: Like the - corresponding guard tests in Erlang, return or - .

-

is_record: Takes an additional parameter, which SHALL - be the result of )]]>, - like in . -

-

'not': Negates its single argument (anything other - than gives ). -

-

'and': Returns if all its arguments - (variable length argument list) evaluate to , else - . Evaluation order is undefined. -

-

'or': Returns if any of its arguments - evaluates to . Variable length argument - list. Evaluation order is undefined. -

-

andalso: Like , but quits evaluating its - arguments as soon as one argument evaluates to something else - than true. Arguments are evaluated left to right. -

-

orelse: Like , but quits evaluating as soon - as one of its arguments evaluates to . Arguments are - evaluated left to right. -

-

'xor': Only two arguments, of which one has to be true - and the other false to return ; otherwise - returns false. -

-

abs, element, hd, length, node, round, size, tl, trunc, '+', '-', '*', 'div', 'rem', 'band', 'bor', 'bxor', 'bnot', 'bsl', 'bsr', '>', '>=', '<', '=<', '=:=', '==', '=/=', '/=', self: Work as the corresponding Erlang bif's (or - operators). In case of bad arguments, the result depends on - the context. In the part of the - expression, the test fails immediately (like in an Erlang - guard), but in the , exceptions are implicitly - caught and the call results in the atom .

+ Functions Allowed in All Types of Match Specifications +

The functions allowed in work as + follows:

+ + + is_atom, is_float, is_integer, is_list, + is_number, is_pid, is_port, is_reference, + is_tuple, is_map, is_binary, is_function + + +

Same as the corresponding guard tests in Erlang, return + or .

+
+ is_record + +

Takes an additional parameter, which must be the result + of )]]>, like in + .

+
+ 'not' + +

Negates its single argument (anything other + than gives ).

+
+ 'and' + +

Returns if all its arguments (variable + length argument list) evaluate to , otherwise + . Evaluation order is undefined.

+
+ 'or' + +

Returns if any of its arguments + evaluates to . Variable length argument + list. Evaluation order is undefined.

+
+ 'andalso' + +

Works as , but quits evaluating its + arguments when one argument evaluates to something else + than true. Arguments are evaluated left to right.

+
+ 'orelse' + +

Works as , but quits evaluating as soon + as one of its arguments evaluates to . + Arguments are evaluated left to right.

+
+ 'xor' + +

Only two arguments, of which one must be true and the + other false to return ; otherwise + returns false.

+
+ abs, element, hd, length, node, + round, size, tl, trunc, '+', + '-', '*', 'div', 'rem', 'band', + 'bor', 'bxor', 'bnot', 'bsl', + 'bsr', '>', '>=', '<', '=<', + '=:=', '==', '=/=', '/=', + self + +

Same as the corresponding Erlang BIFs (or operators). In case of + bad arguments, the result depends on the context. In the + part of the expression, the test + fails immediately (like in an Erlang guard). In the + part, exceptions are implicitly caught + and the call results in the atom .

+
+
- Functions allowed only for tracing -

is_seq_trace: Returns if a sequential - trace token is set for the current process, otherwise . -

-

set_seq_token: Works like - , but returns on success - and on error or bad argument. Only allowed in the - part and only allowed when tracing. -

-

get_seq_token: Works just like - , and is only allowed in the - part when tracing. -

-

message: 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, 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 are desired. - Another special case is 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 are placed - before , it is in fact a "noop"). -

-

Takes one argument, the message. Returns and can - only be used in the part and when tracing. -

-

return_trace: Causes a trace - message to be sent upon return from the current function. - Takes no arguments, returns and can only be used - in the part when tracing. - If the process trace flag - is active the trace message is inhibited. -

-

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 process trace flag - tail recursiveness still remains. -

-

exception_trace: Same as return_trace, - plus; if the traced function exits due to an exception, - an trace message is generated, - whether the exception is caught or not. -

-

process_dump: Returns some textual information about - the current process as a binary. Takes no arguments and is only - allowed in the part when tracing. -

-

enable_trace: With one parameter this function turns - on tracing like the Erlang call , where is the parameter to - . 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 , where P1 is the first and P2 is the second - argument. The process gets its trace messages sent to the same - tracer as the process executing the statement uses. - can not be one of the atoms , or - (unless, of course, they are registered names). - can not be nor - . - Returns and may only be used in - the part when tracing. -

-

disable_trace: With one parameter this function - disables tracing like the Erlang call , where is the parameter to - . With two parameters it works like the - Erlang call , where P1 can - be either a process identifier or a registered name and is given - as the first argument to the match_spec function. - can not be nor - . Returns - and may only be used in the part - when tracing. -

-

trace: 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 not including - but including . 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. When using a tracer module - the module has to be loaded before the match specification is executed. - If it is not loaded the match will fail. - 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 - if any trace property was changed for the - trace target process or if not. It may only - be used in the part when tracing. -

-

caller: - Returns the calling function as a tuple {Module, - Function, Arity} or the atom if the calling - function cannot be determined. May only be used in the - part when tracing. -

-

Note that if a "technically built in function" (i.e. a - function not written in Erlang) is traced, the - function will sometimes return the atom . The calling - Erlang function is not available during such calls. -

-

display: For debugging purposes only; displays the - single argument as an Erlang term on stdout, which is seldom - what is wanted. Returns and may only be used in the - part when tracing. -

-

-get_tcw: - Takes no argument and returns the value of the node's trace - control word. The same is done by - . -

-

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. -

-

-set_tcw: - 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 - . It is only - allowed to use in the part - when tracing. -

-

silent: - Takes one argument. If the argument is , 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 is called in the - part for a traced function. -

-

This mode can also be activated with the flag - to . -

-

If the argument is , the call trace message mode - for the current process is set to normal (non-silent) for - this call and all subsequent. -

-

If the argument is neither nor , - the call trace message mode is unaffected.

+ Functions Allowed Only for Tracing +

The functions allowed only for tracing work as follows:

+ + + is_seq_trace + +

Returns if a sequential trace token is set + for the current process, otherwise .

+
+ set_seq_token + +

Works as , but returns + on success, and + on error or bad argument. Only allowed in the + part and only allowed when tracing.

+
+ get_seq_token + +

Same as and only + allowed in the part when tracing.

+
+ message + +

Sets an additional message appended to the + trace message sent. One can only set one additional message in + the body. Later calls replace the appended message.

+

As a special case, disables + sending of trace messages ('call' and 'return_to') for this function + call, just like if the match specification had not matched. + This can be useful if only the side effects of + the part are desired.

+

Another special case is , which + sets the default behavior, as if the function had no match + specification; trace message is sent with no extra information + (if no other calls to are placed before + , it is in fact a "noop").

+

Takes one argument: the message. Returns + and can only be used in the part and + when tracing.

+
+ return_trace + +

Causes a trace message to be sent + upon return from the current function. Takes no arguments, returns + and can only be used in the + part when tracing. + If the process trace flag is active, the + trace message is inhibited.

+

Warning: If the traced function is tail-recursive, this + match specification function destroys that property. Hence, if a + match specification executing this function is used on a + perpetual server process, it can only be active for a limited + period of time, or the emulator will eventually use all memory in + the host machine and crash. If this match specification function is + inhibited using process trace flag , + tail-recursiveness still remains.

+
+ exception_trace + +

Works as return_trace plus; if the traced function exits + because of an exception, + an trace message is generated, + regardless of the exception is caught or not.

+
+ process_dump + +

Returns some textual information about + the current process as a binary. Takes no arguments and is only + allowed in the part when tracing.

+
+ enable_trace + +

With one parameter this function turns on tracing like the Erlang + call , where + is the parameter to + .

+

With two parameters, the first parameter is to be either a process + identifier or the registered name of a process. In this case tracing + is turned on for the designated process in the same way as in the + Erlang call , where + P1 is the first and P2 is the second argument. The + process gets its trace messages sent to the + same tracer as the process executing the statement uses. + cannot be one of the atoms + , or + (unless they are registered names). + cannot be + or .

+

Returns and can only be used in + the part when tracing.

+
+ disable_trace + +

With one parameter this function disables tracing like the Erlang + call , where + is the parameter to + .

+

With two parameters this function works as the Erlang call + , where P1 + can be either a process identifier or a registered name and is + specified as the first argument to the match specification function. + cannot be + or .

+

Returns and can only be used in the + part when tracing.

+
+ trace + +

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 , + not including , but including + .

+

If a tracer is specified in both lists, the tracer in the + enable list takes precedence. If no tracer is specified, the same + tracer as the process executing the match specification is used.

+

When using a tracer module, + the module must be loaded before the match specification is + executed. If it is not loaded, the match fails.

+

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 if any trace property was changed + for the trace target process, otherwise . + Can only be used in the part when + tracing.

+
+ caller + +

Returns the calling function as a tuple {Module, Function, + Arity} or the atom if the calling + function cannot be determined. Can only be used in the + part when tracing.

+

Notice that if a "technically built in function" (that is, a + function not written in Erlang) is traced, the + function sometimes returns the atom + . The calling + Erlang function is not available during such calls.

+
+ display + +

For debugging purposes only. Displays the single argument as an + Erlang term on stdout, which is seldom what is wanted. + Returns and can only be used in the + part when tracing.

+ +
+ get_tcw + +

Takes no argument and returns the value of the node's trace + control word. The same is done by + .

+

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.

+ +
+ set_tcw + +

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 + . + It is only allowed to use in the + part when tracing.

+
+ silent + +

Takes one argument. If the argument is , + the call trace message mode for the current process is set to + silent for this call and all later calls, that is, call trace + messages are inhibited even if + is called in the + part for a traced function.

+

This mode can also be activated with flag + to + .

+

If the argument is , the call trace + message mode for the current process is set to normal + (non-silent) for this call and all later calls.

+

If the argument is not or + , the call trace message mode is + unaffected.

+
+
-

Note that all "function calls" have to be tuples, - even if they take no arguments. The value of is - the atom() , but the value of is - the pid() of the current process.

+ + +

All "function calls" must be tuples, even if they take no arguments. + The value of is the atom() + , but the value of is + the pid() of the current process.

+
-
+ Match target

Each execution of a match specification is done against a match target term. The format and content of the target term @@ -422,217 +533,268 @@

- Variables and literals -

Variables take the form ']]> where - ]]> is an integer between 0 (zero) and - 100000000 (1e+8), the behavior if the number is outside these - limits is undefined. In the part, the special - variable matches anything, and never gets bound (like - in Erlang). In the - parts, no unbound variables are allowed, why is - interpreted as itself (an atom). Variables can only be bound in - the part. In the and - parts, only variables bound previously may - be used. As a special case, in the - parts, the variable - expands to the whole match target - term and the variable expands to a list - of the values of all bound variables in order - (i.e. ). -

-

In the part, all literals (except the variables - noted above) are interpreted as is. In the - parts, however, the - interpretation is in some ways different. Literals in the - can either be written as is, - which works for all literals except tuples, or by using the - special form , where 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 + Variables and Literals +

Variables take the form ']]>, where + ]]> is an integer between 0 and + 100,000,000 (1e+8). The behavior if the number is outside these limits + is undefined. In the part, the + special variable matches anything, and never gets + bound (like in Erlang).

+ + + +

In the parts, + no unbound variables are allowed, so is + interpreted as itself (an atom). Variables can only be bound in the + part.

+
+ +

In the and + parts, only variables bound + previously can be used.

+
+ +

As a special case, the following apply in the + parts:

+ + +

The variable expands to the whole + match target term. +

+
+ +

The variable expands to a list of the + values of all bound variables in order (that is, + ).

+
+
+
+
+ +

In the part, all literals (except the + variables above) are interpreted "as is".

+ +

In the parts, the + interpretation is in some ways different. Literals in these parts + can either be written "as is", which works for all literals except + tuples, or by using the special form , + where is any Erlang term.

+ +

For tuple literals in the match specification, double tuple parentheses + can also be used, that is, construct them as a tuple of arity one containing a single tuple, which is the one to be constructed. The "double tuple parenthesis" syntax is useful to construct tuples from already bound variables, like in - . Some examples may be needed: -

+ . Examples:

+ - Expression - Variable bindings - Result + Expression + Variable Bindings + Result - {{'$1','$2'}} + {{'$1','$2'}} '$1' = a, '$2' = b {a,b} - {const, {'$1', '$2'}} - doesn't matter + {const, {'$1', '$2'}} + Irrelevant {'$1', '$2'} - a - doesn't matter + a + Irrelevant a - '$1' - '$1' = [] + '$1' + '$1' = [] [] - ['$1'] - '$1' = [] + ['$1'] + '$1' = [] [[]] - [{{a}}] - doesn't matter + [{{a}}] + Irrelevant [{a}] - 42 - doesn't matter + 42 + Irrelevant 42 - "hello" - doesn't matter + "hello" + Irrelevant "hello" - $1 - doesn't matter - 49 (the ASCII value for the character '1') + $1 + Irrelevant + 49 (the ASCII value for + character '1') - Literals in the MatchCondition/MatchBody parts of a match_spec + Literals in MatchCondition/MatchBody Parts of a Match + Specification
- Execution of the match + Execution of the Match

The execution of the match expression, when the runtime system - decides whether a trace message should be sent, goes as follows: -

-

For each tuple in the list and while no - match has succeeded:

- - Match the part against the - match target term, - binding the ']]> variables (much like in - ). - If the cannot match the arguments, the match fails. - - Evaluate each (where only - ']]> variables previously bound in the - can occur) and expect it to return the atom - . As soon as a condition does not evaluate to - , the match fails. If any BIF call generates an - exception, also fail. + decides whether a trace message is to be sent, is as follows:

+ +

For each tuple in the list and while + no match has succeeded:

+ + + +

Match the part against the match target + term, binding the ']]> variables + (much like in ). If the + part cannot match the arguments, the + match fails.

+

Evaluate each (where only + ']]> variables previously bound in the + part can occur) and expect it to return + the atom . When a condition does not evaluate + to , the match fails. If any BIF call + generates an exception, the match also fails.

+
+ +

Two cases can occur:

- If the match_spec is executing when tracing:

- Evaluate each in the same way as the - , but completely ignore the return - values. Regardless of what happens in this part, the match has - succeeded.
- If the match_spec is executed when selecting objects from an ETS table:

- Evaluate the expressions in order and return the value of - the last expression (typically there is only one expression - in this context)
+ +

If the match specification is executing when tracing:

+

Evaluate each in the same way as + the , but ignore the return + values. Regardless of what happens in this part, the match has + succeeded.

+
+ +

If the match specification is executed when selecting objects + from an ets table:

+

Evaluate the expressions in order and return the value of + the last expression (typically there is only one expression + in this context).

+
- Differences between match specifications in ETS and tracing -

ETS match specifications are there to produce a return - value. Usually the contains one single - which defines the return value without having - any side effects. Calls with side effects are not allowed in the - ETS context.

+ + Differences between Match Specifications in ETS and Tracing +

ets match specifications produce a return value. + Usually the contains one single + that defines the return value + without any side effects. Calls with side effects are not allowed in + the ets context.

+

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 's are executed as in an imperative - language, i.e. for their side effects. Functions with side effects + match specification either matches or does not. The effect when the + expression matches is a trace message rather than a returned + term. The s are executed as in an imperative + language, that is, for their side effects. Functions with side effects are also allowed when tracing.

Tracing Examples -

Match an argument list of three where the first and third arguments +

Match an argument list of three, where the first and third arguments are equal:

+ -

Match an argument list of three where the second argument is - a number greater than three:

+ +

Match an argument list of three, where the second argument is + a number > 3:

+ ', '$1', 3}], []}] ]]> -

Match an argument list of three, where the third argument - is a tuple containing argument one and two or a list - beginning with argument one and two (i. e. or - ): -

+ +

Match an argument list of three, where the third argument is + either a tuple containing argument one and two, or a list + beginning with argument one and two (that is, + or ):

+ -

The above problem may also be solved like this:

+ +

The above problem can also be solved as follows:

+ -

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])

+ +

Match two arguments, where the first is a tuple beginning with + a list that in turn begins with the second argument times + two (that is, [{[4,x],y},2] or [{[8], y, z},4]):

+ +

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.

+ numbers, append the process dump to the trace message, otherwise + let the trace message be "as is", but set the sequential trace + token label to 4711:

+ -

As can be noted above, the parameter list can be matched - against a single or an . To replace the - whole - parameter list with a single variable is a special case. In all - other cases the has to be a proper list. -

-

Only generate trace message if trace control word is set to 1:

+ +

As can be noted above, the parameter list can be matched aginst a + single or an . + To replace the whole parameter list with a single variable is a special + case. In all other cases the must be a + proper list.

+ +

Generate a trace message only if the trace control word is set to 1:

+ -

Only generate trace message if there is a seq trace token:

+ +

Generate a trace message only if there is a seq_trace token:

+ -

Remove 'silent' trace flag when first argument is 'verbose' - and add it when it is 'silent':

+ +

Remove the 'silent' trace flag when the first argument is + 'verbose', and add it when it is 'silent':

+ -

Add return_trace message if function is of arity 3:

+ +

Add a return_trace message if the function is of arity 3:

+ -

Only generate trace message if function is of arity 3 and first argument is 'trace':

+ +

Generate a trace message only if the function is of arity 3 and the + first argument is 'trace':

+ ETS Examples -

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.

+

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:

+ -

Match all objects in an ets table with arity > 1 and the first - element is 'gandalf', return element 2.

+ +

Match all objects in an ets table with arity > 1 and the first + element is 'gandalf', and return element 2:

+ =',{size, '$1'},2}], [{element,2,'$1'}]}] ]]> -

In the above example, if the first element had been the key, - it's much more efficient to match that key in the - part than in the part. The search space of - the tables is restricted with regards to the so - that only objects with the matching key are searched. -

-

Match tuples of 3 elements where the second element is either - 'merry' or 'pippin', return the whole objects.

+ +

In this example, if the first element had been the key, it is + much more efficient to match that key in the + part than in the part. + The search space of the tables is restricted with regards to the + so + that only objects with the matching key are searched.

+ +

Match tuples of three elements, where the second element is either + 'merry' or 'pippin', and return the whole objects:

+ -

The function can be useful for testing - complicated ets matches.

+ +

Function can be useful for testing + complicated ets matches.

diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml index 4b5b01d2b1..b3f5e1073b 100644 --- a/erts/doc/src/notes.xml +++ b/erts/doc/src/notes.xml @@ -541,9 +541,7 @@ Own Id: OTP-13440

-

- Add the following NIF API functions:

-

+

Add the following NIF API functions:

enif_cpu_time enif_binary_to_term enif_port_command -

+

- for details of what each function does, see the erl_nif + For details of what each function does, see the erl_nif documentation.

Own Id: OTP-13442

diff --git a/erts/doc/src/part.xml b/erts/doc/src/part.xml index b2abfc62ca..d583b873a0 100644 --- a/erts/doc/src/part.xml +++ b/erts/doc/src/part.xml @@ -30,8 +30,8 @@ part.xml -

The Erlang Runtime System Application ERTS.

+ diff --git a/erts/doc/src/ref_man.xml b/erts/doc/src/ref_man.xml index e45402a397..e3f7b1692b 100644 --- a/erts/doc/src/ref_man.xml +++ b/erts/doc/src/ref_man.xml @@ -30,16 +30,9 @@ application.xml -

The Erlang Runtime System Application ERTS.

- -

By default, the is only guaranteed to be compatible - with other Erlang/OTP components from the same release as - the itself. See the documentation of the system flag - +R on how to communicate - with Erlang/OTP components from earlier releases.

-
+ @@ -56,6 +49,5 @@ - diff --git a/erts/doc/src/run_erl.xml b/erts/doc/src/run_erl.xml index 6b0fef7c0a..21a7f86011 100644 --- a/erts/doc/src/run_erl.xml +++ b/erts/doc/src/run_erl.xml @@ -28,137 +28,184 @@ - 99-12-15 + 1999-12-15 run_erl.xml run_erl - Redirect Erlang input and output streams on Solaris® + Redirect Erlang input and output streams on Solaris. -

This describes the 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 connect to the Erlang console making it - possible to monitor and debug an embedded system remotely.

-

You can read more about the use in the .

+

The program is specific to Solaris/Linux. + This program redirects the standard input and standard + output streams so that all output can be logged. It also lets the + program connect to the Erlang console, making + it possible to monitor and debug an embedded system remotely.

+ +

For more information about the use, see the + + Embedded System User's Guide in System Documentation.

+ - run_erl [-daemon] pipe_dir/ log_dir "exec command [command_arguments]" - Start the Erlang emulator without attached terminal + run_erl [-daemon] pipe_dir/ log_dir "exec command + [command_arguments]" + Start the Erlang emulator without attached terminal. -

The program arguments are:

+

Arguments:

- -daemon - 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. - pipe_dir - This is where to put the named pipe, usually - . It shall be suffixed by a (slash), - i.e. not , but . - log_dir - This is where the log files are written. There will be one - log file, that log progress and - warnings from the 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 will delete - and reuse the oldest log file. - "exec command [command_arguments]" - In the third argument is the to execute - where everything written to stdin and stdout is logged to - . + -daemon + +

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.

+
+ pipe_dir + +

The named pipe, usually . It must be + suffixed by a (slash), that is, + , not + .

+
+ log_dir + +

The log files, that is:

+ + +

One log file, , which logs + progress and warnings from the + program itself.

+
+ +

Up to five log files at maximum 100 KB each with the content + of the standard streams from and to the command. (Both the + number of logs and sizes can be changed by environment + variables, see section Environment Variables + below.)

+

When the logs are full, deletes + and reuses the oldest log file.

+
+
+
+ "exec command [command_arguments]" + +

In the third argument, is the + executable to execute where everything written to stdin + and stdout is logged to .

+
- Notes concerning the log files -

While running, run_erl (as stated earlier) sends all output, - uninterpreted, to a log file. The file is called - , where N is a number. When the log is "full", - default after 100KB, run_erl starts to log in file - , 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:

+ Notes concerning the Log Files +

While running, run_erl (as stated earlier) sends all output, + uninterpreted, to a log file. The file is named + , where N is an integer. When the + log is "full" (default log size is 100 KB), run_erl starts to log + in file , until N reaches a + certain number (default 5), whereupon 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 time stamp and is written, by default, + after 15 minutes of inactivity. Also, if output from Erlang is + logged, but more than 5 minutes (default) has passed since last time + we got anything from Erlang, a time stamp is written in the + log. The "ALIVE" messages look as follows:

+ - ]]> -

while the other timestamps look like this:

+===== ALIVE ]]>
+ +

The other time stamps look as follows:

+ - ]]> -

The 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 - using the format string , which produces - messages on the line of , this can be changed, see below.

+===== ]]> + +

is the date and time the message is + written, default in local time (can be changed to UTC if needed). + It is formatted with the ANSI-C function + using the format string , which + produces messages like + ; this can + be changed, see the next section.

- Environment variables -

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.

+ + Environment Variables +

The following environment variables are recognized by run_erl + and change the logging behavior. For more information, see the previous + section.

+ - RUN_ERL_LOG_ALIVE_MINUTES - 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. - RUN_ERL_LOG_ACTIVITY_MINUTES - 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. - RUN_ERL_LOG_ALIVE_FORMAT - Specifies another format string to be used in the strftime - C library call. i.e specifying this to - will give log messages with timestamps looking like - etc. See the documentation - for the C library function strftime for more - information. Default is . - RUN_ERL_LOG_ALIVE_IN_UTC - 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 - can be modified accordingly by setting the erlang - application variable to . - RUN_ERL_LOG_GENERATIONS - Controls the number of log files written before older - files are being reused. Default is 5, minimum is 2, maximum is 1000. - RUN_ERL_LOG_MAXSIZE - 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. - RUN_ERL_DISABLE_FLOWCNTRL - If defined, disables input and output flow control for the pty opend by run_erl. - Useful if you want to remove any risk of accidentally blocking the flow control - by hit Ctrl-S (instead of Ctrl-D to detach). - Which may result in blocking of the entire beam process - and in the case of running heart as supervisor - even the heart process will be blocked when writing log message to terminal. - Leaving the heart process unable to do its work. + RUN_ERL_LOG_ALIVE_MINUTES + +

How long to wait for output (in minutes) before writing an + "ALIVE" message to the log. Defaults to 15, minimum is 1.

+
+ RUN_ERL_LOG_ACTIVITY_MINUTES + +

How long Erlang needs to be inactive before output is + preceded with a time stamp. Defaults to + RUN_ERL_LOG_ALIVE_MINUTES div 3, minimum is 1.

+
+ RUN_ERL_LOG_ALIVE_FORMAT + +

Specifies another format string to be used in the strftime + C library call. That is, specifying this to + gives + log messages with time stamps like + . For more information, + see the documentation for the C library function strftime. + Defaults to .

+
+ RUN_ERL_LOG_ALIVE_IN_UTC + +

If set to anything else than 0, it makes all + times displayed by run_erl to be in UTC (GMT, CET, MET, + without Daylight Saving Time), rather than in local time. + This does not affect data coming from Erlang, + only the logs output directly by run_erl. Application + SASL can be modified accordingly by setting the Erlang + application variable to + .

+
+ RUN_ERL_LOG_GENERATIONS + +

Controls the number of log files written before older + files are reused. Defaults to 5, minimum is 2, maximum is 1000.

+
+ RUN_ERL_LOG_MAXSIZE + +

The size, in bytes, of a log file before switching to a + new log file. Defaults to 100000, minimum is 1000, maximum is + about 2^30.

+
+ RUN_ERL_DISABLE_FLOWCNTRL + +

If defined, disables input and output flow control for the pty + opend by run_erl. Useful if you want to remove any risk of + accidentally blocking the flow control by using Ctrl-S (instead of + Ctrl-D to detach), which can result in blocking of the entire Beam + process, and in the case of running heart as supervisor even the + heart process becomes blocked when writing log message to terminal, + leaving the heart process unable to do its work.

+
- SEE ALSO -

start(1), start_erl(1)

+ See Also +

start(1), + start_erl(1)

diff --git a/erts/doc/src/start.xml b/erts/doc/src/start.xml index adacf5b98d..6eac47fe94 100644 --- a/erts/doc/src/start.xml +++ b/erts/doc/src/start.xml @@ -28,38 +28,46 @@ - 99-12-15 + 1999-12-15 start.xml start - OTP start script example for Unix + OTP start script example for Unix. -

This describes the script that is an example script on - how to startup the Erlang system in embedded mode on Unix.

-

You can read more about the use in the .

+

The script is an example script on + how to start up the Erlang system in embedded mode on Unix.

+ +

For more information about the use, see the + + Embedded System User's Guide in System Documentation.

+ start [ data_file ] - This is an example script on how to startup the Erlang system in embedded mode on Unix. + Example script on how to start up the Erlang system in embedded + mode on Unix. -

In the example there is one argument

+

Argument:

- data_file - Optional, specifies what file - to use. + data_file + +

Optional. Specifies what file + to use.

+
-

There is also an environment variable that can - be set prior to calling this example that set the directory +

Environment variable can + be set before calling this example, which sets the directory where to find the release files.

- SEE ALSO -

run_erl(1), start_erl(1)

+ See Also +

run_erl(1), + start_erl(1)

diff --git a/erts/doc/src/start_erl.xml b/erts/doc/src/start_erl.xml index 243aeaa717..50f8c58a48 100644 --- a/erts/doc/src/start_erl.xml +++ b/erts/doc/src/start_erl.xml @@ -28,117 +28,142 @@ - 98-08-05 + 1998-08-05 start_erl.xml start_erl - Start Erlang for embedded systems on Windows NT® + Start Erlang for embedded systems on Windows systems. -

This describes the program specific to Windows - NT. Although there exists programs with the same name on other - platforms, their functionality is not the same.

-

The program is distributed both in compiled +

The program is specific to + Windows NT/2000/XP (and later versions of Windows). + Although there are programs with the same name on other + platforms, their functionality is different.

+ +

This program is distributed both in compiled form (under <Erlang root>\\erts-<version>\\bin) and - in source form (under <Erlang - root>\\erts-<version>\\src). - The purpose of the source code is to make it possible to easily - customize the program for local needs, such as cyclic restart - detection etc. There is also a "make"-file, written for the - program distributed with Microsoft® Visual - C++®. The program can however be compiled with - any Win32 C compiler (possibly with slight modifications).

-

The purpose of the program is to aid release handling on - Windows NT®. The program should be called by the + in source form (under <Erlang root>\\erts-<version>\\src). + The purpose of the source code is to ease customization of the + program for local needs, such as cyclic restart + detection. There is also a "make"-file, written for the + program distributed with Microsoft Visual + C++. This program can, however, be compiled with + any Win32 C compiler (possibly with minor modifications).

+ +

This program aids release handling on Windows systems. + The program is to be called by the 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 option).

+ start_erl.data, and start Erlang. Some options to + start_erl are added and removed by the release handler + during upgrade with emulator restart (more specifically option + ).

+ start_erl [<erl options>] ++ [<start_erl options>] - Start the Erlang emulator with the correct release data + Start the Erlang emulator with the correct release data. + -

The program in its original form +

The program in its original form recognizes the following options:

- ++ - Mandatory, delimits start_erl options from normal Erlang - options. Everything on the command line before the - is interpreted as options to be sent to the - program. Everything after is - interpreted as options to itself. - -reldir <release root> - - Mandatory if the environment variable - is not specified and no - -rootdir option is given. Tells start_erl where the - root of the release tree is placed in the file-system (typically - <Erlang root>\\releases). The - file is expected to be - placed in this directory (if not otherwise specified). If - only the -rootdir option is given, the directory is - assumed to be <Erlang root>\\releases. - - -rootdir <Erlang root directory> - - Mandatory if -reldir is not given and there is - no in the environment. This - specifies the Erlang installation root directory (under - which the lib, releases and - erts-<Version> directories are placed). If only - -reldir (or the environment variable - ) is given, the Erlang root is assumed to - be the directory exactly one level above the release - directory. - - -data <data file name> - 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. - -bootflags <boot flags file name> - Optional, specifies a file name relative to actual release - directory (that is the subdirectory of <release - root> where the 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. + ++ + +

Mandatory. Delimits start_erl options from normal Erlang + options. Everything on the command line before + is interpreted as options to be sent to the + program. Everything after + is interpreted as options to + itself.

+
+ -reldir <release root> + +

Mandatory if environment variable + is not specified and no + -rootdir option is specified. Tells start_erl where + the root of the release tree is located in the file system + (typically <Erlang root>\\releases). The + file is expected to be + located in this directory (unless otherwise specified). If + only option -rootdir is specified, the directory is + assumed to be <Erlang root>\\releases.

+
+ -rootdir <Erlang root directory> + +

Mandatory if -reldir is not specified and no + exists in the environment. This + specifies the Erlang installation root directory (under + which the lib, releases, and + erts-<Version> directories are located). If only + -reldir (or environment variable ) + is specified, the Erlang root is assumed to + be the directory exactly one level above the release + directory.

+
+ -data <data file name> + +

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, and so + on). This option is used by the release handler during + upgrade and is not to be used during normal + operation. Normally the release data file is not to be + named differently.

+
+ -bootflags <boot flags file name> + +

Optional. Specifies a file name relative to the release + directory (that is, the subdirectory of <release root> + where the file and others are located). + The contents of this file is appended to the command line + when Erlang is started. This makes it easy to start the + emulator with different options for different releases.

+
- NOTES -

As the source code is distributed, it can easily be modified to - accept other options. The program must still accept the - option with the semantics described above for the - release handler to work correctly.

-

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.

-

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 not change the - option to during emulator restart. - Place the (possibly customized) program so that - it is not overwritten during upgrade.

-

The program's default options are not - sufficient for release handling. The machine - starts should be specified as the program and - the arguments should contain the followed by desired - options.

+ Notes + + +

As the source code is distributed, it can easily be modified to + accept other options. The program must still accept option + with the semantics described above for the + release handler to work correctly.

+
+ +

The Erlang emulator is found by examining the registry keys for + the emulator version specified in the release data file. The new + emulator must be properly installed before the upgrade for + this to work.

+
+ +

Although the program is located together with files specific to the + emulator version, it is not expected to be specific to the + emulator version. The release handler does not change option + to during + emulator restart. Locate the (possibly customized) + program so that it is not overwritten + during upgrade.

+
+ +

The default options of the program are not + sufficient for release handling. The machine started by + is be specified as the + program and the arguments are to contain + followed by the desired options.

+
+
- SEE ALSO -

erlsrv(1), release_handler(3)

+ See Also +

erlsrv(1), + + sasl:release_handler(3)

diff --git a/erts/doc/src/time_correction.xml b/erts/doc/src/time_correction.xml index 236fe679cb..dbaae4d852 100644 --- a/erts/doc/src/time_correction.xml +++ b/erts/doc/src/time_correction.xml @@ -35,12 +35,12 @@
New Extended Time Functionality -

As of OTP 18 (ERTS version 7.0) the time functionality of - Erlang has been extended. This includes a +

As from Erlang/OTP 18 (ERTS 7.0) the time functionality + has been extended. This includes a new API for time and time warp - modes that alter the system behavior when + modes that change the system behavior when system time changes.

The default @@ -106,14 +106,18 @@

POSIX Time

Time since - Epoch. + + Epoch. Epoch is defined to be 00:00:00 UTC, 1970-01-01. - A day in POSIX time - is defined to be exactly 86400 seconds long. Strangely enough + + A day in POSIX time + is defined to be exactly 86400 seconds long. Strangely enough, Epoch is defined to be a time in UTC, and UTC has another definition of how long a day is. Quoting the Open Group - "POSIX time is therefore not necessarily UTC, despite its appearance". + + "POSIX time is therefore not necessarily UTC, despite its + appearance". The effect of this is that when an UTC leap second is inserted, POSIX time either stops for a second, or repeats the last second. If an UTC leap second would be deleted (which has not @@ -157,7 +161,8 @@

The operating systems view of POSIX time. To retrieve it, call - os:system_time(). + + os:system_time(). This may or may not be an accurate view of POSIX time. This time may typically be adjusted both backwards and forwards without limitation. That is, time warps @@ -165,25 +170,26 @@

To get information about the Erlang runtime system's source of OS system time, call - erlang:system_info(os_system_time_source).

+ + erlang:system_info(os_system_time_source).

OS Monotonic Time -

A monotonically increasing time provided by the operating - system. This time does not leap and has a relatively steady +

A monotonically increasing time provided by the OS. + This time does not leap and has a relatively steady frequency although not completely correct. However, it is not uncommon that OS monotonic time stops if the system is suspended. This time typically increases since some unspecified point in time that is not connected to OS system time. - This type of time is not necessarily provided by all - operating systems.

+ This type of time is not necessarily provided by all OSs.

To get information about the Erlang runtime system's source of OS monotonic time, call - erlang:system_info(os_monotonic_time_source).

+ + erlang:system_info(os_monotonic_time_source).

@@ -192,7 +198,8 @@

The Erlang runtime systems view of POSIX time. To retrieve it, call - erlang:system_time().

+ + erlang:system_time().

This time may or may not be an accurate view of POSIX time, and may @@ -211,8 +218,8 @@

A monotonically increasing time provided by the Erlang runtime system. Erlang monotonic time increases since some unspecified point in time. To retrieve it, call - erlang:monotonic_time(). -

+ + erlang:monotonic_time().

The accuracy and precision of Erlang @@ -225,7 +232,8 @@ Accuracy and precision of OS system time - time warp mode used + + time warp mode used @@ -238,16 +246,17 @@ time is the "time engine" that is used for more or less everything that has anything to do with time. All timers, regardless of it is a receive ... after timer, BIF timer, - or a timer in the timer module, are triggered - relative Erlang monotonic time. Even + or a timer in the + stdlib:timer + module, are triggered relative Erlang monotonic time. Even Erlang system time is based on Erlang monotonic time. By adding current Erlang monotonic time with current time offset, you get current Erlang system time.

-

To retrieve current time offset, call - erlang:time_offset/0. -

+

To retrieve the current time offset, call + + erlang:time_offset/0.

@@ -278,7 +287,7 @@ less potent time-keeper than an atomic clock is used.

However, NTP is not fail-safe. The NTP server can be unavailable, - ntp.conf can be wrongly configured, or your computer may + ntp.conf can be wrongly configured, or your computer can sometimes be disconnected from Internet. Furthermore, you can have a user (or even system administrator) who thinks the correct way to handle Daylight Saving Time is to adjust the clock one @@ -327,16 +336,18 @@ implementation in the Erlang runtime system using OS monotonic time. To check if your system has support for OS monotonic time, call - erlang:system_info(os_monotonic_time_source). + + erlang:system_info(os_monotonic_time_source). To check if time correction is enabled on your system, call - erlang:system_info(time_correction).

+ + erlang:system_info(time_correction).

To enable or disable time correction, pass command-line argument - +c [true|false] - to erl.

+ +c [true|false] to + erl(1).

If time correction is disabled, Erlang monotonic time - may warp forwards or stop, or even freeze for extended + can warp forwards or stop, or even freeze for extended periods of time. There are then no guarantees that the frequency of the Erlang monotonic clock is accurate or stable.

@@ -369,7 +380,7 @@ erlang:now/0 are suboptimal from a performance and scalability perspective. So you really want to replace the use of it with other functionality. For examples - of how to replace the use of erlang:now/0, see Section + of how to replace the use of erlang:now/0, see section How to Work with the New API.

@@ -378,7 +389,7 @@ Time Warp Modes

Current Erlang system - time is determined by adding current + time is determined by adding the current Erlang monotonic time with current time offset. The @@ -387,8 +398,8 @@

To set the time warp mode, pass command-line argument +C - [no_time_warp|single_time_warp|multi_time_warp] - to erl.

+ [no_time_warp|single_time_warp|multi_time_warp] to + erl(1).

@@ -398,7 +409,7 @@ not because it is the best mode (which it is not). It is default only because this is how the runtime system behaved until ERTS 7.0. - Ensure that your Erlang code that may execute during a time + Ensure that your Erlang code that can execute during a time warp is time warp safe before enabling other modes.

@@ -422,8 +433,8 @@
Single Time Warp Mode -

This mode is more or less a backwards compatibility mode - as of its introduction.

+

This mode is more or less a backward compatibility mode + as from its introduction.

On an embedded system it is not uncommon that the system has no power supply, not even a battery, when it is @@ -475,11 +486,12 @@

This phase begins when the user finalizes the time offset by calling - erlang:system_flag(time_offset, finalize). + + erlang:system_flag(time_offset, finalize). The finalization can only be performed once.

During finalization, the time offset is adjusted and - fixated so that current Erlang system time aligns with + fixed so that current Erlang system time aligns with the current OS system time. As the time offset can change during the finalization, Erlang system time can do a time warp at this point. The time offset is @@ -488,7 +500,7 @@ correction from now on also makes adjustments to align Erlang system time with OS system time. When the system is in the final phase, it behaves - exactly as in the no + exactly as in no time warp mode.

@@ -520,7 +532,7 @@ may behave very bad.

Assuming that these requirements are fulfilled, - time correction is enabled, and that OS system time + time correction is enabled, and OS system time is adjusted using a time adjustment protocol such as NTP, only small adjustments of Erlang monotonic time are needed to keep system times @@ -529,9 +541,10 @@ inserted (or deleted) leap seconds.

To use this mode, ensure that - all Erlang code that will execute in both phases are + all Erlang code that will execute in both phases is time warp safe.

+

Code executing only in the final phase does not have to be able to cope with the time warp.

@@ -542,13 +555,13 @@

Multi-time warp mode in combination with time correction is the preferred configuration. This as the Erlang runtime system have better performance, scale - better, and behave better on almost all platforms. In - addition, the accuracy and precision of time measurements + better, and behave better on almost all platforms. + Also, the accuracy and precision of time measurements are better. Only Erlang runtime systems executing on ancient platforms benefit from another configuration.

-

The time offset may change at any time without limitations. - That is, Erlang system time may perform time warps both +

The time offset can change at any time without limitations. + That is, Erlang system time can perform time warps both forwards and backwards at any time. As we align Erlang system time with OS system time by changing the time offset, we can enable a time correction that tries @@ -582,8 +595,8 @@ such issues. To improve this, the new API spreads different functionality over multiple functions.

-

To be backwards compatible, erlang:now/0 - remains as is, but you are strongly discouraged from using +

To be backward compatible, erlang:now/0 + remains "as is", but you are strongly discouraged from using it. Many use cases of erlang:now/0 prevents you from using the new multi-time warp @@ -597,38 +610,60 @@

The new API consists of the following new BIFs:

-

erlang:convert_time_unit/3

-

erlang:monotonic_time/0

-

erlang:monotonic_time/1

-

erlang:system_time/0

-

erlang:system_time/1

-

erlang:time_offset/0

-

erlang:time_offset/1

-

erlang:timestamp/0

-

erlang:unique_integer/0

-

erlang:unique_integer/1

-

os:system_time/0

-

os:system_time/1

+

+ erlang:convert_time_unit/3

+

+ erlang:monotonic_time/0

+

+ erlang:monotonic_time/1

+

+ erlang:system_time/0

+

+ erlang:system_time/1

+

+ erlang:time_offset/0

+

+ erlang:time_offset/1

+

+ erlang:timestamp/0

+

+ erlang:unique_integer/0

+

+ erlang:unique_integer/1

+

+ os:system_time/0

+

+ os:system_time/1

-

The new API also consists of extensions of the following existing BIFs:

+

The new API also consists of extensions of the following existing BIFs: +

-

erlang:monitor(time_offset, clock_service)

-

erlang:system_flag(time_offset, finalize)

-

erlang:system_info(os_monotonic_time_source)

-

erlang:system_info(os_system_time_source)

-

erlang:system_info(time_offset)

-

erlang:system_info(time_warp_mode)

-

erlang:system_info(time_correction)

-

erlang:system_info(start_time)

-

erlang:system_info(end_time)

+

+ erlang:monitor(time_offset, clock_service)

+

+ erlang:system_flag(time_offset, finalize)

+

+ erlang:system_info(os_monotonic_time_source)

+

+ erlang:system_info(os_system_time_source)

+

+ erlang:system_info(time_offset)

+

+ erlang:system_info(time_warp_mode)

+

+ erlang:system_info(time_correction)

+

+ erlang:system_info(start_time)

+

+ erlang:system_info(end_time)

New Erlang Monotonic Time -

Erlang monotonic time as such is new as of ERTS 7.0. +

Erlang monotonic time as such is new as from ERTS 7.0. It is introduced to detach time measurements, such as elapsed time from calendar time. In many use cases there is a need to measure elapsed time or specify a time relative to another point @@ -649,7 +684,7 @@ modes, and only fully separated in the multi-time warp mode. All other modes than the - multi-time warp mode are for backwards + multi-time warp mode are for backward compatibility reasons. When using these modes, the accuracy of Erlang monotonic time suffer, as the adjustments of Erlang monotonic time in these @@ -672,15 +707,17 @@

To be able to react to a change in Erlang system time, you must be able to detect that it - happened. The change in Erlang system time occurs when + happened. The change in Erlang system time occurs when the current time offset is changed. We have therefore introduced the possibility to monitor the time offset using - erlang:monitor(time_offset, clock_service). + + erlang:monitor(time_offset, clock_service). A process monitoring the time offset is sent a message on the following format when the time offset is changed:

- {'CHANGE', MonitorReference, time_offset, clock_service, NewTimeOffset} + +{'CHANGE', MonitorReference, time_offset, clock_service, NewTimeOffset}
@@ -690,8 +727,8 @@ produces unique and strictly monotonically increasing values. To detach this functionality from time measurements, we have introduced - erlang:unique_integer(). -

+ + erlang:unique_integer().

@@ -699,27 +736,28 @@ How to Work with the New API

Previously erlang:now/0 was the only option for doing many things. This section deals with some things that - erlang:now/0 can be used for, and how you are to - these using the new API.

+ erlang:now/0 can be used for, and how you use the new API.

Retrieve Erlang System Time

- Use erlang:now/0 to retrieve current Erlang system time. + Use erlang:now/0 to retrieve the current Erlang system time.

Use - erlang:system_time/1 - to retrieve current Erlang system time on the + + erlang:system_time/1 + to retrieve the current Erlang system time on the time unit of your choice.

-

If you want the same format as returned by erlang:now/0, use - erlang:timestamp/0. -

+

If you want the same format as returned by erlang:now/0, + use + erlang:timestamp/0. +

@@ -728,28 +766,31 @@ Measure Elapsed Time

- Take timestamps with erlang:now/0 and calculate + Take time stamps with erlang:now/0 and calculate the difference in time with - timer:now_diff/2. + + timer:now_diff/2 in STDLIB.

- Take timestamps with - erlang:monotonic_time/0 + Take time stamps with + + erlang:monotonic_time/0 and calculate the time difference using ordinary subtraction. - The result will be in native + The result is in native time unit. If you want to convert the result to another time unit, you can use - erlang:convert_time_unit/3. -

- -

An easier way to do this is to use - erlang:monotonic_time/1 + + erlang:convert_time_unit/3. +

+

An easier way to do this is to use + + erlang:monotonic_time/1 with the desired time unit. However, you can then lose accuracy and precision. -

+

@@ -758,7 +799,7 @@ Determine Order of Events

- Determine the order of events by saving a timestamp + Determine the order of events by saving a time stamp with erlang:now/0 when the event occurs.

@@ -766,8 +807,9 @@

Determine the order of events by saving the integer returned by - erlang:unique_integer([monotonic]) - when the event occurs. These integers will be strictly + + erlang:unique_integer([monotonic]) + when the event occurs. These integers are strictly monotonically ordered on current runtime system instance corresponding to creation time.

@@ -779,7 +821,7 @@ Determine Order of Events with Time of the Event

- Determine the order of events by saving a timestamp + Determine the order of events by saving a time stamp with erlang:now/0 when the event occurs.

@@ -795,18 +837,19 @@ Time = erlang:monotonic_time(), UMI = erlang:unique_integer([monotonic]), EventTag = {Time, UMI} -

These tuples will be strictly monotonically ordered - on current runtime system instance according to +

These tuples are strictly monotonically ordered + on the current runtime system instance according to creation time. It is important that the monotonic time is in the first element (the most - significant element when comparing 2-tuples). Using + significant element when comparing two-tuples). Using the monotonic time in the tuples, you can calculate time between events.

If you are interested in Erlang system time at the time when the event occurred, you can also save the time offset before or after saving the events using - erlang:time_offset/0. + + erlang:time_offset/0. Erlang monotonic time added with the time offset corresponds to Erlang system time.

@@ -814,7 +857,7 @@ EventTag = {Time, UMI} can change, and you want to get the actual Erlang system time when the event occurred, you can save the time offset as a third element in the tuple - (the least significant element when comparing 3-tuples).

+ (the least significant element when comparing three-tuples).

@@ -830,10 +873,12 @@ EventTag = {Time, UMI}

Use the value returned from - erlang:unique_integer/0 + + erlang:unique_integer/0 to create a name unique on the current runtime system instance. If you only want positive integers, you can use - erlang:unique_integer([positive]). + + erlang:unique_integer([positive]).

@@ -849,12 +894,15 @@ EventTag = {Time, UMI}

Seed random number generation using a combination of - erlang:monotonic_time(), - erlang:time_offset(), - erlang:unique_integer(), + + erlang:monotonic_time(), + + erlang:time_offset(), + + erlang:unique_integer(), and other functionality.

-
+

To sum up this section: Do not use erlang:now/0.

@@ -867,9 +915,9 @@ EventTag = {Time, UMI}

It can be required that your code must run on a variety of OTP installations of different OTP releases. If so, you cannot use the new API out of the box, as it will - not be available on old pre OTP 18 releases. The solution + not be available on old pre-OTP 18 releases. The solution is not to avoid using the new API, as your - code then would not benefit from the scalability + code would then not benefit from the scalability and accuracy improvements made. Instead, use the new API when available, and fall back on erlang:now/0 when the new API is unavailable.

@@ -879,16 +927,20 @@ EventTag = {Time, UMI} - erlang:system_info(start_time) + + erlang:system_info(start_time) - erlang:system_info(end_time) + + erlang:system_info(end_time) - erlang:system_info(os_monotonic_time_source) + + erlang:system_info(os_monotonic_time_source) - erlang:system_info(os_system_time_source)) + + erlang:system_info(os_system_time_source)) diff --git a/erts/doc/src/tty.xml b/erts/doc/src/tty.xml index b2866c82cf..51db1ba8e2 100644 --- a/erts/doc/src/tty.xml +++ b/erts/doc/src/tty.xml @@ -22,7 +22,7 @@ - tty - A command line interface + tty - A Command-Line Interface ETX/B/SFP C. Granbom @@ -32,24 +32,48 @@ A tty.xml -

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. - is started when Erlang is started with the command:

-

erl

-

operates in one of two modes:

+

is a simple command-line interface program where + keystrokes are collected and interpreted. Completed lines are sent to the + shell for interpretation. A simple history mechanism saves previous lines, + which can be edited before sending them to the shell. + is started when Erlang is started with the following command:

+ +
+erl
+ +

operates in one of two modes:

+ -

normal mode, in which lines of text can be edited and sent to the shell.

+

Normal mode, in which text lines can be edited and sent to the + shell.

-

shell break mode, which allows the user to kill the current shell, start multiple shells etc. Shell break mode is started by typing Control G.

+

Shell break mode, which allows the user to kill the current shell, + start multiple shells, and so on.

Normal Mode -

In normal mode keystrokes from the user are collected and interpreted by . Most of the emacs line editing commands are supported. The following is a complete list of the supported line editing commands.

-

Note: The notation means pressing the control key and the letter simultaneously. means pressing the key followed by the letter . and represent the keys with the same name on the keyboard, whereas and represent the corresponding arrow keys. -

+

In normal mode keystrokes from the user are collected and interpreted by + . Most of the Emacs line-editing commands + are supported. The following is a complete list of the supported + line-editing commands.

+ +

Typographic conventions:

+ + + C-a means pressing the Ctrl key and the letter + a simultaneously. + M-f means pressing the Esc key and the letter + f in sequence. + Home and End represent the keys with the same + name on the keyboard. + Left and Right represent the corresponding arrow + keys. + + Key Sequence @@ -121,11 +145,13 @@ C-n - Fetch next line from the history buffer + Fetch next line from the history + buffer C-p - Fetch previous line from the history buffer + Fetch previous line from the history + buffer C-t @@ -139,23 +165,18 @@ C-y Insert previously killed text - tty text editing + tty Text Editing
Shell Break Mode -

tty enters shell break mode when you type Control G. In this mode you can:

+

In this mode the following can be done:

+ - -

Kill or suspend the current shell

-
- -

Connect to a suspended shell

-
- -

Start a new shell

-
+ Kill or suspend the current shell + Connect to a suspended shell + Start a new shell
diff --git a/erts/doc/src/werl.xml b/erts/doc/src/werl.xml index 1a3cb6f502..995095c0d8 100644 --- a/erts/doc/src/werl.xml +++ b/erts/doc/src/werl.xml @@ -28,62 +28,91 @@ 1 Bjarne Däcker - 98-01-26 + 1998-01-26 A werl.xml werl The Erlang Emulator -

On Windows, the preferred way to start the Erlang system for interactive use is:

+

On Windows, the preferred way to start the Erlang system for interactive + use is as follows:

+

]]>

-

This will start Erlang in its own window, with fully - functioning command-line editing and scrollbars. All flags +

This starts Erlang in its own window, with fully + functioning command-line editing and scrollbars. All flags except work as they do for - the erl command.

+ command erl.

+ + + +

To copy text to the clipboard, use Ctrl-C.

+
+ +

To paste text, use Ctrl-V.

+
+ +

To interrupt the runtime system or the shell process (depending + on what has been specified with system flag +B), use + Ctrl-Break.

+
+
-

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.

In cases where you want to redirect standard input and/or - standard output or use Erlang in a pipeline, the werl is - not suitable, and the erl program should be used instead.

+ standard output or use Erlang in a pipeline, werl is + not suitable, and the erl program is to be used instead.

-

The werl window is in many ways modelled after the xterm +

The werl window is in many ways modeled after the xterm window present on other platforms, as the xterm model - fits well with line oriented command based interaction. This - means that selecting text is line oriented rather than rectangle - oriented.

- -

To select text in the werl 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 right mouse-button. The whole area between your - first selection and the point where you right-clicked will be - included in the selection.

+ fits well with line-oriented command-based interaction. This + means that selecting text is line-oriented rather than + rectangle-oriented.

-

The selected text is copied to the clipboard by either - pressing Ctrl-C, using the menu or pressing the copy - button in the toolbar.

+ + +

To select text in the werl window, press and hold + the left mouse button and drag the mouse over the text you want + to select. If the selection crosses line boundaries, the + selected text consists of complete lines where applicable + (just like in a word processor).

+
+ +

To select more text than fits + in the window, start by selecting a small part in the + beginning of the text you want, then use the scrollbar + to view the end of the desired selection, point to it, and press + the right mouse button. The whole area between your + first selection and the point where you right-clicked is + included in the selection.

+
+ +

To copy the selected text to the clipboard, either + use Ctrl-C, use the menu, or press the copy + button in the toolbar.

+
+
-

Pasted text is always inserted at the current prompt position - and will be interpreted by Erlang as usual keyboard input.

+

Pasted text is inserted at the current prompt position + and is interpreted by Erlang as usual keyboard input.

-

Previous command lines can be retrieved by pressing the Up - arrow or by pressing Ctrl-P. 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 + + +

To retrieve previous command lines, press the Up arrow or + use Ctrl-P.

+ + + +

A drop-down box in the toolbar contains the command + history. Selecting a command in the drop-down box inserts the command + at the prompt, as if you used the keyboard to retrieve the command.

- -

Closing the werl window will stop the Erlang emulator.

+ + +

To stop the Erlang emulator, close the werl window.

+
+
diff --git a/erts/doc/src/zlib.xml b/erts/doc/src/zlib.xml index a3c94e4a7f..138414a880 100644 --- a/erts/doc/src/zlib.xml +++ b/erts/doc/src/zlib.xml @@ -30,13 +30,18 @@ zlib.xml zlib - Zlib Compression interface. + zlib compression interface. -

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.

-

A typical (compress) usage looks like:

+

This module provides an API for the zlib library + (www.zlib.net). + It is used to compress and decompress data. + The data format is described by + RFC 1950, + RFC 1951, and + RFC 1952.

+ +

A typical (compress) usage is as follows:

+
 Z = zlib:open(),
 ok = zlib:deflateInit(Z,default),
@@ -50,29 +55,25 @@ Last = zlib:deflate(Z, [], finish),
 ok = zlib:deflateEnd(Z),
 zlib:close(Z),
 list_to_binary([Compressed|Last])
+

In all functions errors, {'EXIT',{Reason,Backtrace}}, - might be thrown, where Reason describes the - error. Typical reasons are:

+ can be thrown, where Reason describes the error.

+ +

Typical Reasonss:

+ badarg - -

Bad argument

+ Bad argument. data_error - -

The data contains errors

+ The data contains errors. stream_error - -

Inconsistent stream state

-
+ Inconsistent stream state. einval - -

Bad value or wrong function called

-
+ Bad value or wrong function called. {need_dictionary,Adler32} - -

See inflate/2

+ See inflate/2.
@@ -81,7 +82,7 @@ list_to_binary([Compressed|Last]) -

A zlib stream, see open/0. +

A zlib stream, see open/0.

@@ -104,129 +105,144 @@ list_to_binary([Compressed|Last]) + - Calculate the adler checksum + Calculate the Adler checksum. -

Calculate the Adler-32 checksum for Data.

+

Calculates the Adler-32 checksum for Data.

+ - Calculate the adler checksum + Calculate the Adler checksum. -

Update a running Adler-32 checksum for Data. - If Data is the empty binary or the empty iolist, this function returns - the required initial value for the checksum.

+

Updates a running Adler-32 checksum for Data. + If Data is the empty binary or the empty iolist, + this function returns the required initial value for the checksum.

+

Example:

 Crc = lists:foldl(fun(Data,Crc0) ->
                       zlib:adler32(Z, Crc0, Data),
                   end, zlib:adler32(Z,<< >>), Datas)
+ - Combine two Adler-32 checksums + Combine two Adler-32 checksums. -

Combine two Adler-32 checksums into one. For two binaries or iolists, - Data1 and Data2 with sizes of Size1 and - Size2, with Adler-32 checksums Adler1 and - Adler2. adler32_combine/4 returns the Adler - checksum of [Data1,Data2], requiring - only Adler1, Adler2, and Size2. -

+

Combines two Adler-32 checksums into one. For two binaries or + iolists, Data1 and Data2 with sizes of Size1 + and Size2, with Adler-32 checksums + Adler1 and Adler2.

+

This function returns the Adler checksum of + [Data1,Data2], requiring only Adler1, + Adler2, and Size2.

+ - Close a stream + Close a stream.

Closes the stream referenced by Z.

+ - Compress data with standard zlib functionality + Compress data with standard zlib functionality. -

Compress data (with zlib headers and checksum).

+

Compresses data with zlib headers and checksum.

+ - Get current CRC + Get current CRC. -

Get the current calculated CRC checksum.

+

Gets the current calculated CRC checksum.

+ - Calculate CRC + Calculate CRC. -

Calculate the CRC checksum for Data.

+

Calculates the CRC checksum for Data.

+ - Calculate CRC + Calculate CRC. -

Update a running CRC checksum for Data. - If Data is the empty binary or the empty iolist, this function returns - the required initial value for the crc.

+

Updates a running CRC checksum for Data. + If Data is the empty binary or the empty iolist, + this function returns the required initial value for the CRC.

+

Example:

 Crc = lists:foldl(fun(Data,Crc0) ->
                       zlib:crc32(Z, Crc0, Data),
                   end, zlib:crc32(Z,<< >>), Datas)
+ - Combine two CRC's + Combine two CRCs. -

Combine two CRC checksums into one. For two binaries or iolists, - Data1 and Data2 with sizes of Size1 and - Size2, with CRC checksums CRC1 and - CRC2. crc32_combine/4 returns the CRC - checksum of [Data1,Data2], requiring - only CRC1, CRC2, and Size2. -

+

Combines two CRC checksums into one. For two binaries or iolists, + Data1 and Data2 with sizes of Size1 and + Size2, with CRC checksums CRC1 + and CRC2.

+

This function returns the CRC checksum of + [Data1,Data2], requiring only CRC1, + CRC2, and Size2.

- Compress data + Compress data.

Same as deflate(Z, Data, none).

+ - Compress data + Compress data. -

deflate/3 compresses as much data as possible, and - stops when the input buffer becomes empty. It may introduce +

Compresses as much data as possible, and + stops when the input buffer becomes empty. It can introduce some output latency (reading input without producing any output) except when forced to flush.

-

If the parameter Flush is set to sync, all +

If Flush is set to sync, 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.

-

If Flush is set to full, all output is flushed as with - sync, 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 full too often can seriously degrade - the compression.

-

If the parameter Flush is set to finish, - pending input is processed, pending output is flushed and - deflate/3 returns. Afterwards the only possible - operations on the stream are deflateReset/1 or deflateEnd/1.

-

Flush can be set to finish immediately after - deflateInit if all compression is to be done in one step.

+ Flushing can degrade compression for some compression algorithms; + thus, use it only when necessary.

+

If Flush is set to full, all output is + flushed as with sync, 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 + full too often can seriously degrade the compression.

+

If Flush is set to finish, + pending input is processed, pending output is flushed, and + deflate/3 returns. Afterwards the only possible operations + on the stream are + deflateReset/1 or + deflateEnd/1.

+

Flush can be set to finish immediately + after deflateInit + if all compression is to be done in one step.

+

Example:

- 
 zlib:deflateInit(Z),
 B1 = zlib:deflate(Z,Data),
 B2 = zlib:deflate(Z,<< >>,finish),
@@ -237,184 +253,231 @@ list_to_binary([B1,B2])
- End deflate session + End deflate session. -

End the deflate session and cleans all data used. - Note that this function will throw an data_error - exception if the last call to - deflate/3 was not called with Flush set to - finish.

+

Ends the deflate session and cleans all data used. Notice that this + function throws a data_error exception if the last call to + deflate/3 + was not called with Flush set to finish.

- Initialize a session for compression + Initialize a session for compression.

Same as zlib:deflateInit(Z, default).

+ - Initialize a session for compression + Initialize a session for compression. -

Initialize a zlib stream for compression.

-

Level decides the compression level to be used, 0 - (none), gives no compression at all, 1 - (best_speed) gives best speed and 9 - (best_compression) gives best compression.

+

Initializes a zlib stream for compression.

+

Level decides the compression level to be + used:

+ + 0 (none), gives no compression + 1 (best_speed) gives best speed + 9 (best_compression) gives best compression +
+ - Initialize a session for compression + Initialize a session for compression.

Initiates a zlib stream for compression.

-

The Level parameter decides the compression level to be - used, 0 (none), gives no compression at all, 1 - (best_speed) gives best speed and 9 - (best_compression) gives best compression.

-

The Method parameter decides which compression method to use, - currently the only supported method is deflated.

-

The WindowBits parameter is the base two logarithm - of the window size (the size of the history buffer). It - should be in the range 8 through 15. Larger values - of this parameter result in better compression at the - expense of memory usage. The default value is 15 if - deflateInit/2. A negative WindowBits - value suppresses the zlib header (and checksum) from the - stream. Note that the zlib source mentions this only as a - undocumented feature.

-

The MemLevel parameter specifies how much memory - should be allocated for the internal compression - state. MemLevel=1 uses minimum memory but is slow and - reduces compression ratio; MemLevel=9 uses maximum - memory for optimal speed. The default value is 8.

-

The Strategy parameter is used to tune - the compression algorithm. Use the value default for - normal data, filtered for data produced by a filter (or - predictor), huffman_only to force Huffman encoding - only (no string match), or rle to limit match - distances to one (run-length encoding). Filtered data - consists mostly of small values with a somewhat random - distribution. In this case, the compression algorithm is tuned - to compress them better. The effect of filteredis to - force more Huffman coding and less string matching; it is - somewhat intermediate between default and - huffman_only. rle is designed to be almost as - fast as huffman_only, but give better compression for PNG - image data. The Strategy parameter only - affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately.

+ + Level + +

Compression level to use:

+ + 0 (none), gives no compression + 1 (best_speed) gives best speed + 9 (best_compression) gives best compression + +
+ Method + +

Compression method to use, currently the only supported method + is deflated.

+
+ WindowBits + +

The base two logarithm of the window size (the size of the + history buffer). It is to be in the range 8 through 15. Larger + values result in better compression at the expense of memory + usage. Defaults to 15 if + deflateInit/2 is used. A negative + WindowBits value suppresses the zlib header + (and checksum) from the stream. Notice that the zlib source + mentions this only as a undocumented feature.

+
+ MemLevel + +

Specifies how much memory is to be allocated for the internal + compression state: MemLevel=1 uses minimum + memory but is slow and reduces compression ratio; + MemLevel=9 uses maximum memory for optimal + speed. Defaults to 8.

+
+ Strategy + +

Tunes the compression algorithm. Use the following values:

+ + default for normal data + filtered for data produced by a filter (or + predictor) + huffman_only to force Huffman encoding only + (no string match) + rle to limit match distances to one (run-length + encoding) + +

Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is + tuned to compress them better. The effect of filtered is to + force more Huffman coding and less string matching; it is somewhat + intermediate between default and huffman_only. + rle is designed to be almost as fast as + huffman_only, but gives better compression for PNG image + data.

+

Strategy affects only the compression ratio, + but not the correctness of the compressed output even if it is not + set appropriately.

+
+
+ - Dynamicly update deflate parameters + Dynamicly update deflate parameters. -

Dynamically update the compression level and compression - strategy. The interpretation of Level and - Strategy is as in deflateInit/6. This can be +

Dynamically updates the compression level and compression + strategy. The interpretation of Level and + Strategy is as in + deflateInit/6. + 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 deflate/3.

-

Before the call of deflateParams, the stream state must be set as for - a call of deflate/3, since the currently available input may have to - be compressed and flushed.

+ old level (and can be flushed); the new level takes + effect only at the next call of + deflate/3.

+

Before the call of deflateParams, the stream state must be + set as for a call of deflate/3, as the currently available + input may have to be compressed and flushed.

+ - Reset the deflate session - -

This function is equivalent to deflateEnd/1 - followed by deflateInit/[1|2|6], but does not free - and reallocate all the internal compression state. The - stream will keep the same compression level and any other + Reset the deflate session. + +

Equivalent to + deflateEnd/1 + followed by + deflateInit/1,2,6, + but does not free and reallocate all the internal compression state. + The stream keeps the same compression level and any other attributes.

+ - Initialize the compression dictionary + Initialize the compression dictionary. -

Initializes the compression dictionary from the given byte - sequence without producing any compressed output. This - function must be called immediately after - deflateInit/[1|2|6] or deflateReset/1, before - any call of deflate/3. The compressor and - decompressor must use exactly the same dictionary (see - inflateSetDictionary/2). The adler checksum of the - dictionary is returned.

+

Initializes the compression dictionary from the specified byte + sequence without producing any compressed output.

+

This function must be called immediately after + deflateInit/1,2,6 or + deflateReset/1, + before any call of + deflate/3. + The compressor and decompressor must use the same dictionary (see + + inflateSetDictionary/2).

+

The Adler checksum of the dictionary is returned.

+ - Get buffer size + Get buffer size. -

Get the size of intermediate buffer.

+

Gets the size of the intermediate buffer.

+ - Uncompress data with gz header + Uncompress data with gz header. -

Uncompress data (with gz headers and checksum).

+

Uncompresses data with gz headers and checksum.

+ - Compress data with gz header + Compress data with gz header. -

Compress data (with gz headers and checksum).

+

Compresses data with gz headers and checksum.

+ - Decompress data + Decompress data. -

inflate/2 decompresses as much data as possible. - It may introduce some output latency (reading +

Decompresses as much data as possible. + It can introduce some output latency (reading input without producing any output).

If a preset dictionary is needed at this point (see - inflateSetDictionary below), inflate/2 throws a - {need_dictionary,Adler} exception where Adler is - the adler32 checksum of the dictionary chosen by the - compressor.

+ + inflateSetDictionary/2), inflate/2 throws a + {need_dictionary,Adler} exception, where Adler is + the Adler-32 checksum of the dictionary chosen by the compressor.

+ - Read next uncompressed chunk + Read next uncompressed chunk. -

Read next chunk of uncompressed data, initialized by - inflateChunk/2.

-

This function should be repeatedly called, while it returns +

Reads the next chunk of uncompressed data, initialized by + inflateChunk/2.

+

This function is to be repeatedly called, while it returns {more, Decompressed}.

+ - Decompress data with limited output size + Decompress data with limited output size. -

Like inflate/2, but decompress no more data than - will fit in the buffer configured via setBufSize/2. +

Like inflate/2, + but decompresses no more data than will fit in the buffer configured + through setBufSize/2. Is is useful when decompressing a stream with a high compression - ratio such that a small amount of compressed input may expand up to - 1000 times. - It returns {more, Decompressed}, when there is more output - available, and inflateChunk/1 should be used to read it. - It may introduce some output latency (reading + ratio, such that a small amount of compressed input can expand up to + 1000 times.

+

This function returns {more, Decompressed}, when there is + more output available, and + inflateChunk/1 + is to be used to read it.

+

This function can introduce some output latency (reading input without producing any output).

If a preset dictionary is needed at this point (see - inflateSetDictionary below), inflateChunk/2 throws a - {need_dictionary,Adler} exception where Adler is - the adler32 checksum of the dictionary chosen by the - compressor.

- + + inflateSetDictionary/2), this function throws a + {need_dictionary,Adler} exception, where Adler is + the Adler-32 checksum of the dictionary chosen by the compressor.

+

Example:

 walk(Compressed, Handler) ->
     Z = zlib:open(),
@@ -429,65 +492,76 @@ loop(Z, Handler, {more, Uncompressed}) ->
     Handler(Uncompressed),
     loop(Z, Handler, zlib:inflateChunk(Z));
 loop(Z, Handler, Uncompressed) ->
-    Handler(Uncompressed).
-        
+ Handler(Uncompressed).
+ - End inflate session + End inflate session. -

End the inflate session and cleans all data used. Note - that this function will throw a data_error exception +

Ends the inflate session and cleans all data used. Notice + that this function throws a data_error exception if no end of stream was found (meaning that not all data has been uncompressed).

+ - Initialize a session for decompression + Initialize a session for decompression. -

Initialize a zlib stream for decompression.

+

Initializes a zlib stream for decompression.

+ - Initialize a session for decompression + Initialize a session for decompression. -

Initialize decompression session on zlib stream.

-

The WindowBits parameter is the base two logarithm +

Initializes a decompression session on zlib stream.

+

WindowBits is the base two logarithm of the maximum window size (the size of the history buffer). - It should be in the range 8 through 15. - The default value is 15 if inflateInit/1 is used. - If a compressed stream with a larger window size is - given as input, inflate() will throw the data_error - exception. A negative WindowBits value makes zlib ignore the - zlib header (and checksum) from the stream. Note that the zlib - source mentions this only as a undocumented feature.

+ It is to be in the range 8 through 15. Default to 15 if + inflateInit/1 + is used.

+

If a compressed stream with a larger window size is specified as + input, inflate/2 + throws the data_error exception.

+

A negative WindowBits value makes zlib + ignore the zlib header (and checksum) from the stream. Notice that + the zlib source mentions this only as a undocumented feature.

+ - >Reset the inflate session + >Reset the inflate session. -

This function is equivalent to inflateEnd/1 followed - by inflateInit/1, but does not free and reallocate all - the internal decompression state. The stream will keep - attributes that may have been set by inflateInit/[1|2].

+

Equivalent to + inflateEnd/1 + followed by + inflateInit/1, + but does not free and reallocate all the internal decompression state. + The stream will keep attributes that could have been set by + inflateInit/1,2.

+ - Initialize the decompression dictionary + Initialize the decompression dictionary. -

Initializes the decompression dictionary from the given +

Initializes the decompression dictionary from the specified uncompressed byte sequence. This function must be called - immediately after a call of inflate/2 if this call - threw a {need_dictionary,Adler} exception. - The dictionary chosen by the - compressor can be determined from the Adler value thrown - by the call to inflate/2. The compressor and decompressor - must use exactly the same dictionary (see deflateSetDictionary/2).

+ immediately after a call of + inflate/2 + if this call threw a {need_dictionary,Adler} exception. + The dictionary chosen by the compressor can be determined from the + Adler value thrown by the call to inflate/2. + The compressor and decompressor must use the same dictionary (see + + deflateSetDictionary/2).

Example:

 unpack(Z, Compressed, Dict) ->
@@ -500,39 +574,44 @@ unpack(Z, Compressed, Dict) ->
      end.
+ - Open a stream and return a stream reference + Open a stream and return a stream reference. -

Open a zlib stream.

+

Opens a zlib stream.

+ - Set buffer size + Set buffer size.

Sets the intermediate buffer size.

+ - Uncompress data with standard zlib functionality + Uncompress data with standard zlib functionality. -

Uncompress data (with zlib headers and checksum).

+

Uncompresses data with zlib headers and checksum.

+ - Uncompress data without the zlib headers + Uncompress data without the zlib headers. -

Uncompress data (without zlib headers and checksum).

+

Uncompresses data without zlib headers and checksum.

+ - Compress data without the zlib headers + Compress data without the zlib headers. -

Compress data (without zlib headers and checksum).

+

Compresses data without zlib headers and checksum.

-- cgit v1.2.3