diff options
Diffstat (limited to 'erts/doc')
-rw-r--r-- | erts/doc/src/absform.xml | 13 | ||||
-rw-r--r-- | erts/doc/src/erl.xml | 52 | ||||
-rw-r--r-- | erts/doc/src/erl_dist_protocol.xml | 4 | ||||
-rw-r--r-- | erts/doc/src/erl_nif.xml | 259 | ||||
-rw-r--r-- | erts/doc/src/erl_tracer.xml | 370 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 521 | ||||
-rw-r--r-- | erts/doc/src/match_spec.xml | 149 |
7 files changed, 1096 insertions, 272 deletions
diff --git a/erts/doc/src/absform.xml b/erts/doc/src/absform.xml index 13756ddfdc..bfabb7f042 100644 --- a/erts/doc/src/absform.xml +++ b/erts/doc/src/absform.xml @@ -68,22 +68,12 @@ <item>If D is a module declaration consisting of the forms <c>F_1</c>, ..., <c>F_k</c>, then Rep(D) = <c>[Rep(F_1), ..., Rep(F_k)]</c>.</item> - <item>If F is an attribute <c>-behavior(Behavior)</c>, then - Rep(F) = <c>{attribute,LINE,behavior,Behavior}</c>.</item> - <item>If F is an attribute <c>-behaviour(Behaviour)</c>, then - Rep(F) = <c>{attribute,LINE,behaviour,Behaviour}</c>.</item> - <item>If F is an attribute <c>-compile(Options)</c>, then - Rep(F) = <c>{attribute,LINE,compile,Options}</c>.</item> <item>If F is an attribute <c>-export([Fun_1/A_1, ..., Fun_k/A_k])</c>, then Rep(F) = <c>{attribute,LINE,export,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item> - <item>If F is an attribute <c>-export_type([Type_1/A_1, ..., Type_k/A_k])</c>, then - Rep(F) = <c>{attribute,LINE,export_type,[{Type_1,A_1}, ..., {Type_k,A_k}]}</c>.</item> <item>If F is an attribute <c>-import(Mod,[Fun_1/A_1, ..., Fun_k/A_k])</c>, then Rep(F) = <c>{attribute,LINE,import,{Mod,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}}</c>.</item> <item>If F is an attribute <c>-module(Mod)</c>, then Rep(F) = <c>{attribute,LINE,module,Mod}</c>.</item> - <item>If F is an attribute <c>-optional_callbacks([Fun_1/A_1, ..., Fun_k/A_k])</c>, then - Rep(F) = <c>{attribute,LINE,optional_callbacks,[{Fun_1,A_1}, ..., {Fun_k,A_k}]}</c>.</item> <item>If F is an attribute <c>-file(File,Line)</c>, then Rep(F) = <c>{attribute,LINE,file,{File,Line}}</c>.</item> <item>If F is a function declaration @@ -636,6 +626,9 @@ <item>If A is an association type <c>K => V</c>, where <c>K</c> and <c>V</c> are types, then Rep(A) = <c>{type,LINE,map_field_assoc,[Rep(K),Rep(V)]}</c>.</item> + <item>If A is an association type <c>K := V</c>, where + <c>K</c> and <c>V</c> are types, then Rep(A) = + <c>{type,LINE,map_field_exact,[Rep(K),Rep(V)]}</c>.</item> </list> </section> diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index e13470c83c..1bbde7f1e0 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -627,11 +627,48 @@ <p>Sets the default binary virtual heap size of processes to the size <c><![CDATA[Size]]></c>.</p> </item> + <marker id="+hmax"/> + <tag><c><![CDATA[+hmax Size]]></c></tag> + <item> + <p>Sets the default maximum heap size of processes to the size + <c><![CDATA[Size]]></c>. If <c>+hmax</c> is not given, the default is <c>0</c> + which means that no maximum heap size is used. + For more information, see the documentation of + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <marker id="+hmaxel"/> + <tag><c><![CDATA[+hmaxel true|false]]></c></tag> + <item> + <p>Sets whether to send an error logger message for processes that reach + the maximum heap size or not. If <c>+hmaxel</c> is not given, the default is <c>true</c>. + For more information, see the documentation of + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> + <marker id="+hmaxk"/> + <tag><c><![CDATA[+hmaxk true|false]]></c></tag> + <item> + <p>Sets whether to kill processes that reach the maximum heap size or not. If + <c>+hmaxk</c> is not given, the default is <c>true</c>. For more information, + see the documentation of + <seealso marker="erlang#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>.</p> + </item> <tag><c><![CDATA[+hpds Size]]></c></tag> <item> <p>Sets the initial process dictionary size of processes to the size <c><![CDATA[Size]]></c>.</p> </item> + <tag><marker id="+hmqd"><c>+hmqd off_heap|on_heap|mixed</c></marker></tag> + <item><p> + Sets the default value for the process flag + <c>message_queue_data</c>. If <c>+hmqd</c> is not + passed, <c>mixed</c> will be the default. For more information, + see the documentation of + <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data, + MQD)</c></seealso>. + </p></item> <tag><c><![CDATA[+K true | false]]></c></tag> <item> <p>Enables or disables the kernel poll functionality if @@ -1361,21 +1398,6 @@ <seealso marker="kernel:error_logger#warning_map/0">error_logger(3)</seealso> for further information.</p> </item> - <tag><c><![CDATA[+xFlag Value]]></c></tag> - <item> - <p>Default process flag settings.</p> - <taglist> - <tag><marker id="+xmqd"><c>+xmqd off_heap|on_heap|mixed</c></marker></tag> - <item><p> - Sets the default value for the process flag - <c>message_queue_data</c>. If <c>+xmqd</c> is not - passed, <c>mixed</c> will be the default. For more information, - see the documentation of - <seealso marker="erlang#process_flag_message_queue_data"><c>process_flag(message_queue_data, - MQD)</c></seealso>. - </p></item> - </taglist> - </item> <tag><c><![CDATA[+zFlag Value]]></c></tag> <item> <p>Miscellaneous flags.</p> diff --git a/erts/doc/src/erl_dist_protocol.xml b/erts/doc/src/erl_dist_protocol.xml index b435d5c9b4..f9fa981d9a 100644 --- a/erts/doc/src/erl_dist_protocol.xml +++ b/erts/doc/src/erl_dist_protocol.xml @@ -364,14 +364,14 @@ If Result > 0, the packet only consists of [119, Result]. NodeInfo is, as expressed in Erlang: </p> <code> - io:format("active name ~ts at port ~p, fd = ~p ~n", + io:format("active name ~ts at port ~p, fd = ~p~n", [NodeName, Port, Fd]). </code> <p> or </p> <code> - io:format("old/unused name ~ts at port ~p, fd = ~p~n", + io:format("old/unused name ~ts at port ~p, fd = ~p ~n", [NodeName, Port, Fd]). </code> diff --git a/erts/doc/src/erl_nif.xml b/erts/doc/src/erl_nif.xml index 7546f7ef81..33a4fee182 100644 --- a/erts/doc/src/erl_nif.xml +++ b/erts/doc/src/erl_nif.xml @@ -138,29 +138,6 @@ ok automatically unloaded when the module code that it belongs to is purged by the code server.</p> - <p><marker id="lengthy_work"/> - As mentioned in the <seealso marker="#WARNING">warning</seealso> text at - the beginning of this document it is of vital importance that a native function - return relatively quickly. It is hard to give an exact maximum amount - of time that a native function is allowed to work, but as a rule of thumb - a well-behaving native function should return to its caller before a - millisecond has passed. This can be achieved using different approaches. - If you have full control over the code to execute in the native - function, the best approach is to divide the work into multiple chunks of - work and call the native function multiple times, either directly from Erlang code - or by having a native function schedule a future NIF call via the - <seealso marker="#enif_schedule_nif"> enif_schedule_nif</seealso> function. Function - <seealso marker="#enif_consume_timeslice">enif_consume_timeslice</seealso> can be - used to help with such work division. In some cases, however, this might not - be possible, e.g. when calling third-party libraries. Then you typically want - to dispatch the work to another thread, return - from the native function, and wait for the result. The thread can send - the result back to the calling thread using message passing. Information - about thread primitives can be found below. If you have built your system - with <em>the currently experimental</em> support for dirty schedulers, - you may want to try out this functionality by dispatching the work to a - <seealso marker="#dirty_nifs">dirty NIF</seealso>, - which does not have the same duration restriction as a normal NIF.</p> </description> <section> <title>FUNCTIONALITY</title> @@ -328,38 +305,161 @@ ok </list></p> </item> - <tag>Long-running NIFs</tag> - <item><p><marker id="dirty_nifs"/>Native functions - <seealso marker="#lengthy_work"> - must normally run quickly</seealso>, as explained earlier in this document. They - generally should execute for no more than a millisecond. But not all native functions - can execute so quickly; for example, functions that encrypt large blocks of data or - perform lengthy file system operations can often run for tens of seconds or more.</p> - <p>If the functionality of a long-running NIF can be split so that its work can be - achieved through a series of shorter NIF calls, the application can either make that series - of NIF calls from the Erlang level, or it can call a NIF that first performs a chunk of the - work, then invokes the <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso> - function to schedule another NIF call to perform the next chunk. The final call scheduled - in this manner can then return the overall result. Breaking up a long-running function in - this manner enables the VM to regain control between calls to the NIFs, thereby avoiding - degraded responsiveness, scheduler load balancing problems, and other strange behaviours.</p> - <p>A NIF that cannot be split and cannot execute in a millisecond or less is called a "dirty NIF" - because it performs work that the Erlang runtime cannot handle cleanly. - <em>Note that the dirty NIF functionality described here is experimental</em> and that you have to - enable support for dirty schedulers when building OTP in order to try the functionality out. - Applications that make use of such functions must indicate to the runtime that the functions are - dirty so they can be handled specially. To schedule a dirty NIF for execution, the - appropriate flags value can be set for the NIF in its <seealso marker="#ErlNifFunc">ErlNifFunc</seealso> - entry, or the application can call <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso>, - passing to it a pointer to the dirty NIF to be executed and indicating with the <c>flags</c> - argument whether it expects the operation to be CPU-bound or I/O-bound.</p> - <note><p>Dirty NIF support is available only when the emulator is configured with dirty - schedulers enabled. This feature is currently disabled by default. To determine whether - the dirty NIF API is available, native code can check to see if the C preprocessor macro - <c>ERL_NIF_DIRTY_SCHEDULER_SUPPORT</c> is defined. Also, if the Erlang runtime was built - without threading support, dirty schedulers are disabled. To check at runtime for the presence - of dirty scheduler threads, code can use the <seealso marker="#enif_system_info"><c> - enif_system_info()</c></seealso> API function.</p></note> + <tag><marker id="lengthy_work"/>Long-running NIFs</tag> + + <item><p> + As mentioned in the <seealso marker="#WARNING">warning</seealso> text at + the beginning of this document it is of <em>vital importance</em> 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.</p> + + <p>The + <seealso marker="#enif_consume_timeslice">enif_consume_timeslice()</seealso> + function can be used to inform the runtime system about the lenght of the + NIF call. It should typically always be used unless the NIF executes very + quickly.</p> + + <p>If the NIF call is too lenghty one needs to handle this in one of the + following ways in order to avoid degraded responsiveness, scheduler load + balancing problems, and other strange behaviours:</p> + + <taglist> + <tag>Yielding NIF</tag> + <item> + <p> + If the functionality of a long-running NIF can be split so that + its work can be achieved through a series of shorter NIF calls, + the application can either make that series of NIF calls from the + Erlang level, or it can call a NIF that first performs a chunk of + the work, then invokes the + <seealso marker="#enif_schedule_nif">enif_schedule_nif</seealso> + function to schedule another NIF call to perform the next chunk. + The final call scheduled in this manner can then return the + overall result. Breaking up a long-running function in + this manner enables the VM to regain control between calls to the + NIFs. + </p> + <p> + This approach is always preferred over the other alternatives + described below. This both from a performance perspective and + a system characteristics perspective. + </p> + </item> + + <tag>Threaded NIF</tag> + <item> + <p> + This is accomplished by dispatching the work to another thread + managed by the NIF library, return from the NIF, and wait for the + result. The thread can send the result back to the Erlang + process using <seealso marker="#enif_send">enif_send</seealso>. + Information about thread primitives can be found below. + </p> + </item> + + <tag><marker id="dirty_nifs"/>Dirty NIF</tag> + <item> + + <note> + <p> + <em>The dirty NIF functionality described here + is experimental</em>. Dirty NIF support is available only when + the emulator is configured with dirty schedulers enabled. This + feature is 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 + <seealso marker="#enif_system_info"><c>enif_system_info()</c></seealso> + API function. + </p> + </note> + + <p> + A NIF that cannot be split and cannot execute in a millisecond or + less is called a "dirty NIF" because it performs work that the + Erlang runtime 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. To schedule a dirty + NIF for execution, the appropriate flags value can be set for the + NIF in its <seealso marker="#ErlNifFunc"><c>ErlNifFunc</c></seealso> + entry, or the application can call + <seealso marker="#enif_schedule_nif"><c>enif_schedule_nif</c></seealso>, + passing to it a pointer to the dirty NIF to be executed and + indicating with the <c>flags</c> argument whether it expects the + operation to be CPU-bound or I/O-bound. A dirty NIF executing + on a dirty scheduler does not have the same duration restriction + as a normal NIF. + </p> + + <p> + 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 + <seealso marker="erlang#system_flag_multi_scheduling"><c>erlang:system_flag(multi_scheduling, + block)</c></seealso>, might also take a very long time to + complete. This since all ongoing dirty operations on all + dirty schedulers need to complete before the the block + operation can complete. + </p> + + <p> + A lot of operations communicating with a process executing a + dirty NIF can, however, complete while it is executing the + dirty NIF. For example, retreiving information about it via + <c>process_info()</c>, setting its group leader, + register/unregister its name, etc. + </p> + + <p> + 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 registered names, + ETS tables, etc will be released. All links and monitors + will be triggered. The actual execution of the NIF will + however <em>not</em> be stopped. The NIF can safely contiue + 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 + <seealso marker="#enif_is_current_process_alive"><c>enif_is_current_process_alive</c></seealso>. + Communication using + <seealso marker="#enif_send"><c>enif_send</c></seealso>, + and <seealso marker="#enif_port_command"><c>enif_port_command</c></seealso> + 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. + </p> + + <p>Currently known issues that are planned to be fixed:</p> + <list> + <item> + <p> + 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 operatin implies delaying <em>all</em> code + loding operations which might cause severe problems for + the system as a whole. + </p> + </item> + </list> + + </item> + </taglist> + </item> </taglist> </section> @@ -508,6 +608,10 @@ typedef struct { CPU-bound, its <c>flags</c> field should be set to <c>ERL_NIF_DIRTY_JOB_CPU_BOUND</c>, or for I/O-bound jobs, <c>ERL_NIF_DIRTY_JOB_IO_BOUND</c>.</p> + <note><p>If one of the + <c>ERL_NIF_DIRTY_JOB_*_BOUND</c> flags is set, and the runtime + system has no support for dirty schedulers, the runtime system + will refuse to load the NIF library.</p></note> </item> <tag><marker id="ErlNifBinary"/>ErlNifBinary</tag> <item> @@ -963,6 +1067,13 @@ typedef enum { <fsummary>Determine if a term is a binary</fsummary> <desc><p>Return true if <c>term</c> is a binary</p></desc> </func> + <func><name><ret>int</ret><nametext>enif_is_current_process_alive(ErlNifEnv* env)</nametext></name> + <fsummary>Determine if currently executing process is alive or not.</fsummary> + <desc><p>Return true if currently executing process is currently alive; otherwise + false.</p> + <p>This function can only be used from a NIF-calling thread, and with an + environment corresponding to currently executing processes.</p></desc> + </func> <func><name><ret>int</ret><nametext>enif_is_empty_list(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> <fsummary>Determine if a term is an empty list</fsummary> <desc><p>Return true if <c>term</c> is an empty list.</p></desc> @@ -993,15 +1104,10 @@ typedef enum { <func><name><ret>int</ret><nametext>enif_is_on_dirty_scheduler(ErlNifEnv* env)</nametext></name> <fsummary>Check to see if executing on a dirty scheduler thread</fsummary> <desc> - <p>Check to see if the current NIF is executing on a dirty scheduler thread. If the - emulator is built with threading support, calling <c>enif_is_on_dirty_scheduler</c> - from within a dirty NIF returns true. It returns false when the calling NIF is a regular - NIF running on a normal scheduler thread, or when the emulator is built without threading - support.</p> - <note><p>This function is available only when the emulator is configured with dirty - schedulers enabled. This feature is currently disabled by default. To determine whether - the dirty NIF API is available, native code can check to see if the C preprocessor macro - <c>ERL_NIF_DIRTY_SCHEDULER_SUPPORT</c> is defined.</p></note> + <p>Check to see if the current NIF is executing on a dirty scheduler thread. If + executing on a dirty scheduler thread true returned; otherwise false.</p> + <p>This function can only be used from a NIF-calling thread, and with an + environment corresponding to currently executing processes.</p> </desc> </func> <func><name><ret>int</ret><nametext>enif_is_pid(ErlNifEnv* env, ERL_NIF_TERM term)</nametext></name> @@ -1015,7 +1121,8 @@ typedef enum { <func><name><ret>int</ret><nametext>enif_is_port_alive(ErlNifEnv* env, ErlNifPort *port_id)</nametext></name> <fsummary>Determine if a local port is alive or not.</fsummary> <desc><p>Return true if <c>port_id</c> is currently alive.</p> - <p>This function can only be used in a from a NIF-calling thread.</p></desc> + <p>This function is only thread-safe when the emulator with SMP support is used. + It can only be used in a non-SMP emulator from a NIF-calling thread.</p></desc> </func> <func><name><ret>int</ret><nametext>enif_is_process_alive(ErlNifEnv* env, ErlNifPid *pid)</nametext></name> <fsummary>Determine if a local process is alive or not.</fsummary> @@ -1483,9 +1590,7 @@ enif_map_iterator_destroy(env, &iter); <fsummary>Send a port_command to to_port</fsummary> <desc> <p>This function works the same as <seealso marker="erlang#port_command-2">erlang:port_command/2</seealso> - except that it is always completely asynchronous. This call may return false - if it detects that the port is already dead, otherwise it will return true. - </p> + except that it is always completely asynchronous.</p> <taglist> <tag><c>env</c></tag> <item>The environment of the calling process. May not be NULL.</item> @@ -1504,7 +1609,10 @@ enif_map_iterator_destroy(env, &iter); calls to <c>enif_alloc_env</c>, <c>enif_make_copy</c>, <c>enif_port_command</c> and <c>enif_free_env</c> into one call. This optimization is only usefull when a majority of the terms are to be copied from <c>env</c> to the <c>msg_env</c>.</p> - <p>The call may return false if it detects that the command failed for some reason. Otherwise true is returned.</p> + <p>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, <c>*to_port</c> does not refer to a local port, if currently + executing process, i.e. the sender, is not alive, or if <c>msg</c> is invalid.</p> <p>See also: <seealso marker="#enif_get_local_port"><c>enif_get_local_port</c></seealso>.</p> </desc> </func> @@ -1635,7 +1743,9 @@ enif_map_iterator_destroy(env, &iter); <tag><c>msg</c></tag> <item>The message term to send.</item> </taglist> - <p>Return true on success, or false if <c>*to_pid</c> does not refer to an alive local process.</p> + <p>Return true if the message was successfully sent; otherwise, false. The send + operation will fail if <c>*to_pid</c> does not refer to an alive local process, + or if currently executing process, i.e. the sender, is not alive.</p> <p>The message environment <c>msg_env</c> with all its terms (including <c>msg</c>) will be invalidated by a successful call to <c>enif_send</c>. The environment should either be freed with <seealso marker="#enif_free_env">enif_free_env</seealso> @@ -1653,6 +1763,15 @@ enif_map_iterator_destroy(env, &iter); <desc><p>Get the byte size of a resource object <c>obj</c> obtained by <seealso marker="#enif_alloc_resource">enif_alloc_resource</seealso>.</p></desc> </func> + + <func><name><ret>int</ret><nametext>enif_snprintf(char *str, size_t size, const char *format, ...)</nametext></name> + <fsummary>Format strings and Erlang terms</fsummary> + <desc> + <p>Similar to <c>snprintf</c> but this format string also accepts <c>"%T"</c> which formats Erlang terms. + </p> + </desc> + </func> + <func> <name><ret>void</ret><nametext>enif_system_info(ErlNifSysInfo *sys_info_ptr, size_t size)</nametext></name> <fsummary>Get information about the Erlang runtime system</fsummary> diff --git a/erts/doc/src/erl_tracer.xml b/erts/doc/src/erl_tracer.xml index 1e8e78b25f..d4c8bbad31 100644 --- a/erts/doc/src/erl_tracer.xml +++ b/erts/doc/src/erl_tracer.xml @@ -54,12 +54,20 @@ </description> <datatypes> + <datatype> <name name="trace_tag_send" /> </datatype> + <datatype> <name name="trace_tag_receive" /> </datatype> + <datatype> <name name="trace_tag_call" /> </datatype> + <datatype> <name name="trace_tag_procs" /> </datatype> + <datatype> <name name="trace_tag_ports" /> </datatype> + <datatype> <name name="trace_tag_running_procs" /> </datatype> + <datatype> <name name="trace_tag_running_ports" /> </datatype> + <datatype> <name name="trace_tag_gc" /> </datatype> <datatype> <name name="trace_tag" /> <desc> <p>The different trace tags that the tracer will be called with. Each trace tag is described in greater detail in - <seealso marker="#trace">Module:trace/6</seealso> + <seealso marker="#Module:trace/6">Module:trace/6</seealso> </p> </desc> </datatype> @@ -73,7 +81,7 @@ <datatype> <name name="trace_opts" /> <desc> - <p>The options for the tracee. + <p>The options for the tracee.</p> <taglist> <tag><c>timestamp</c></tag> <item>If not set to <c>undefined</c>, the tracer has been requested to @@ -82,10 +90,9 @@ <item>If not set to <c>true</c>, the tracer has been requested to include the output of a match specification that was run.</item> <tag><c>scheduler_id</c></tag> - <item>Set to a number of the scheduler id is to be included by the tracer. + <item>Set to a number if the scheduler id is to be included by the tracer. Otherwise it is set to <c>undefined</c>.</item> </taglist> - </p> </desc> </datatype> <datatype> @@ -105,8 +112,31 @@ <title>CALLBACK FUNCTIONS</title> <p>The following functions should be exported from a <c>erl_tracer</c> callback module.</p> + <taglist> + <tag><seealso marker="#Module:enabled/3"><c>Module:enabled/3</c></seealso></tag> + <item>Mandatory</item> + <tag><seealso marker="#Module:trace/6"><c>Module:trace/6</c></seealso></tag> + <item>Mandatory</item> + <tag><seealso marker="#Module:enabled_procs/3"><c>Module:enabled_procs/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_procs/6"><c>Module:trace_procs/6</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_ports/3"><c>Module:enabled_ports/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_ports/6"><c>Module:trace_ports/6</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_running_ports/3"><c>Module:enabled_running_ports/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_running_ports/6"><c>Module:trace_running_ports/6</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:enabled_running_procs/3"><c>Module:enabled_running_procs/3</c></seealso></tag> + <item>Optional</item> + <tag><seealso marker="#Module:trace_running_procs/6"><c>Module:trace_running_procs/6</c></seealso></tag> + <item>Optional</item> + </taglist> + </section> - <marker id="enabled"></marker> + <funcs> <func> <name>Module:enabled(TraceTag, TracerState, Tracee) -> Result</name> @@ -114,46 +144,44 @@ <type> <v>TraceTag = <seealso marker="#type-trace_tag">trace_tag()</seealso> | trace_status</v> <v>TracerState = term()</v> - <v>Tracee = <seealso marker="#type-trace_tag">tracee()</seealso></v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> <v>Result = trace | discard | remove</v> </type> <desc> - <p>This callback will be called whenever a trace point is triggered. It + <p>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 <c>trace</c> is returned the necessary trace data will be created and the trace call-back of the tracer will be called. If <c>discard</c> is returned, this trace call - will be discarded and no call to trace will be done. If - <c>remove</c> is returned, the VM will attempt to remove this tracer - from the tracee, together with any trace flags set on the tracee. + will be discarded and no call to trace will be done. </p> <p><c>trace_status</c> is a special type of <c>TraceTag</c> 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.</p> - <p>This function may be called multiple times per trace point, so it + using this tracer. If <c>remove</c> is returned when the <c>trace_status</c> + is checked, the tracer will be removed from the tracee.</p> + <p>This function may be called multiple times per tracepoint, so it is important that it is both fast and side effect free.</p> </desc> </func> - <marker id="trace"></marker> <func> <name>Module:trace(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> <fsummary>Check if a trace event should be generated.</fsummary> <type> <v>TraceTag = <seealso marker="#type-trace_tag">trace_tag()</seealso></v> <v>TracerState = term()</v> - <v>Tracee = <seealso marker="#type-trace_tag">tracee()</seealso></v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> <v>FirstTraceTerm = term()</v> <v>SecondTraceTerm = term() | undefined</v> <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> <v>Result = ok</v> </type> <desc> - <p>This callback will be called when a trace point is triggered and - the <seealso marker="#enabled">Module:enabled/3</seealso> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled/3">Module:enabled/3</seealso> callback returned <c>trace</c>. In it any side effects needed by - the tracer should be done. The trace point payload is located in + the tracer should be done. The tracepoint payload is located in the <c>FirstTraceTerm</c> and <c>SecondTraceTerm</c>. The content of the TraceTerms depends on which <c>TraceTag</c> has been triggered. The <c>FirstTraceTerm</c> and <c>SecondTraceTerm</c> correspond to the @@ -181,6 +209,303 @@ see the <seealso marker="kernel:seq_trace">seq_trace</seealso> manual.</p> </desc> </func> + + <func> + <name>Module:enabled_procs(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>procs</c></seealso> + is triggered.</p> + <p>If <c>enabled_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_procs(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_procs">trace_tag()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_procs/3">Module:enabled_procs/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_procs/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_ports(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_ports">trace_tag_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>ports</c></seealso> + is triggered.</p> + <p>If <c>enabled_ports/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_ports(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_ports">trace_tag()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_ports/3">Module:enabled_ports/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_ports/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_running_procs(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>running_procs | running</c></seealso> + is triggered.</p> + <p>If <c>enabled_running_procs/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_running_procs(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_procs">trace_tag_running_procs()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_running_procs/3">Module:enabled_running_procs/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_running_procs/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_running_ports(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_ports">trace_tag_running_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>running_ports</c></seealso> + is triggered.</p> + <p>If <c>enabled_running_ports/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_running_ports(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_running_ports">trace_tag_running_ports()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_running_ports/3">Module:enabled_running_ports/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_running_ports/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_call(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_call">trace_tag_call()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>call | return_to</c></seealso> + is triggered.</p> + <p>If <c>enabled_call/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_call(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_call">trace_tag_call()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_call/3">Module:enabled_call/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_call/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_send(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>send</c></seealso> + is triggered.</p> + <p>If <c>enabled_send/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_send(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_send">trace_tag_send()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_send/3">Module:enabled_send/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_send/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_receive(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_receive">trace_tag_receive()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>'receive'</c></seealso> + is triggered.</p> + <p>If <c>enabled_receive/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_receive(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_receive">trace_tag_receive()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_receive/3">Module:enabled_receive/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_receive/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:enabled_garbage_collection(TraceTag, TracerState, Tracee) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>Result = trace | discard | remove</v> + </type> + <desc> + <p>This callback will be called whenever a tracepoint with trace flag + <seealso marker="erlang#trace-3"><c>garbage_collection</c></seealso> + is triggered.</p> + <p>If <c>enabled_garbage_collection/3</c> is not defined <c>enabled/3</c> will be called instead.</p> + </desc> + </func> + + <func> + <name>Module:trace_garbage_collection(TraceTag, TracerState, Tracee, FirstTraceTerm, SecondTraceTerm, Opts) -> Result</name> + <fsummary>Check if a trace event should be generated.</fsummary> + <type> + <v>TraceTag = <seealso marker="#type-trace_tag_gc">trace_tag_gc()</seealso></v> + <v>TracerState = term()</v> + <v>Tracee = <seealso marker="#type-tracee">tracee()</seealso></v> + <v>FirstTraceTerm = term()</v> + <v>SecondTraceTerm = term() | undefined</v> + <v>Opts = <seealso marker="#type-trace_opts">trace_opts()</seealso></v> + <v>Result = ok</v> + </type> + <desc> + <p>This callback will be called when a tracepoint is triggered and + the <seealso marker="#Module:enabled_garbage_collection/3">Module:enabled_garbage_collection/3</seealso> + callback returned <c>trace</c>.</p> + <p>If <c>trace_garbage_collection/6</c> is not defined <c>trace/6</c> will be called instead.</p> + </desc> + </func> + </funcs> <section> <marker id="example"></marker> @@ -273,7 +598,7 @@ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data, } /* - * argv[0]: Trace Tag + * argv[0]: TraceTag * argv[1]: TracerState * argv[2]: Tracee */ @@ -282,8 +607,11 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) ErlNifPid to_pid; if (enif_get_local_pid(env, argv[1], &to_pid)) if (!enif_is_process_alive(env, &to_pid)) - /* tracer is dead so we should remove this trace point */ - return enif_make_atom(env, "remove"); + if (enif_is_identical(enif_make_atom(env, "trace_status"), argv[0])) + /* tracer is dead so we should remove this tracepoint */ + return enif_make_atom(env, "remove"); + else + return enif_make_atom(env, "discard"); /* Only generate trace for when tracer != tracee */ if (enif_is_identical(argv[1], argv[2])) @@ -301,7 +629,7 @@ static ERL_NIF_TERM enabled(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]) } /* - * argv[0]: Trace Tag, should only be 'send' + * argv[0]: TraceTag, should only be 'send' * argv[1]: TracerState, process to send {argv[2], argv[4]} to * argv[2]: Tracee * argv[3]: Message, ignored diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index ee34f28b90..e0723127f2 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -4322,6 +4322,7 @@ os_prompt% </pre> </desc> </func> + <marker id="process_flag_min_heap_size"/> <func> <name name="process_flag" arity="2" clause_i="3"/> <fsummary>Sets process flag <c>min_heap_size</c> for the calling process.</fsummary> @@ -4340,9 +4341,95 @@ os_prompt% </pre> <p>Returns the old value of the flag.</p> </desc> </func> - <marker id="process_flag_message_queue_data"/> + <marker id="process_flag_max_heap_size"/> <func> <name name="process_flag" arity="2" clause_i="5"/> + <type name="max_heap_size"/> + <fsummary>Sets process flag <c>max_heap_size</c> for the calling process.</fsummary> + <desc> + <p> + This flag sets the maximum heap size for the calling process. + If <c><anno>MaxHeapSize</anno></c> is an integer, the system default + values for <c>kill</c> and <c>error_logger</c> are used. + <taglist> + <tag><c>size</c></tag> + <item> + <p> + The maximum size in words of the process. If set to zero, the + heap size limit is disabled. Badarg will be thrown if the value is + smaller than + <seealso marker="#process_flag_min_heap_size"><c>min_heap_size</c></seealso>. + The size check is only done when a garbage collection is triggered. + </p> + <p> + <c>size</c> is the entire heap of the process when garbage collection + is triggered, this includes all generational heaps, the process stack, + any <seealso marker="#process_flag_message_queue_data"> + messages that are considered to be part of the heap</seealso> and any + extra memory that the garbage collector needs during collection. + </p> + <p> + <c>size</c> is the same as can be retrieved using + <seealso marker="#process_info_total_heap_size"> + <c>erlang:process_info(Pid, total_heap_size)</c></seealso>, + or by adding <c>heap_block_size</c>, <c>old_heap_block_size</c> + and <c>mbuf_size</c> from <seealso marker="#process_info_garbage_collection_info"> + <c>erlang:process_info(Pid, garbage_collection_info)</c></seealso>. + </p> + </item> + <tag><c>kill</c></tag> + <item> + <p> + When set to <c>true</c> the runtime system will send an + untrappable exit signal with reason <c>kill</c> to the process + if the maximum heap size is reached. The garbage collection + that triggered the <c>kill</c> will not be completed, instead the + process will exit as soon as is possible. When set to <c>false</c> + no exit signal will be sent to the process, instead it will + continue executing. + </p> + <p> + If <c>kill</c> is not defined in the map + the system default will be used. The default system default + is <c>true</c>. It can be changed by either the erl + <seealso marker="erl#+hmaxk">+hmaxk</seealso> option, + or <seealso marker="#system_flag_max_heap_size"><c> + erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>. + </p> + </item> + <tag><c>error_logger</c></tag> + <item> + <p> + When set to <c>true</c> the runtime system will send a + message to the current <seealso marker="kernel:error_logger"><c>error_logger</c></seealso> + containing details about the process when the maximum + heap size is reached. One <c>error_logger</c> report will + be sent each time the limit is reached. + </p> + <p> + If <c>error_logger</c> is not defined in the map the system + default will be used. The default system default is <c>true</c>. + It can be changed by either the erl <seealso marker="erl#+hmaxel">+hmaxel</seealso> + option, or <seealso marker="#system_flag_max_heap_size"><c> + erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>. + </p> + </item> + <p> + The heap size of a process is quite hard to predict, especially the + amount of memory that is used during the garbage collection. When + contemplating using this option, it is recommended to first run + it in production with <c>kill</c> set to <c>false</c> and inspect + the <c>error_logger</c> reports to see what the normal peak sizes + of the processes in the system is and then tune the value + accordingly. + </p> + </taglist> + </p> + </desc> + </func> + <marker id="process_flag_message_queue_data"/> + <func> + <name name="process_flag" arity="2" clause_i="6"/> <fsummary>Set process flag <c>message_queue_data</c> for the calling process</fsummary> <type name="message_queue_data"/> <desc> @@ -4371,7 +4458,7 @@ os_prompt% </pre> </taglist> <p> The default <c>message_queue_data</c> process flag is determined - by the <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> + by the <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso> <c>erl</c> command line argument. </p> <p> @@ -4392,7 +4479,7 @@ os_prompt% </pre> </desc> </func> <func> - <name name="process_flag" arity="2" clause_i="6"/> + <name name="process_flag" arity="2" clause_i="7"/> <fsummary>Sets process flag <c>priority</c> for the calling process.</fsummary> <type name="priority_level"/> <desc> @@ -4466,7 +4553,7 @@ os_prompt% </pre> </func> <func> - <name name="process_flag" arity="2" clause_i="7"/> + <name name="process_flag" arity="2" clause_i="8"/> <fsummary>Sets process flag <c>save_calls</c> for the calling process.</fsummary> <desc> <p><c><anno>N</anno></c> must be an integer in the interval 0..10000. @@ -4497,7 +4584,7 @@ os_prompt% </pre> </func> <func> - <name name="process_flag" arity="2" clause_i="8"/> + <name name="process_flag" arity="2" clause_i="9"/> <fsummary>Sets process flag <c>sensitive</c> for the calling process.</fsummary> <desc> <p>Sets or clears flag <c>sensitive</c> for the current process. @@ -4551,6 +4638,7 @@ os_prompt% </pre> <type name="process_info_result_item"/> <type name="priority_level"/> <type name="stack_item"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <desc> <p>Returns a list containing <c><anno>InfoTuple</anno></c>s with @@ -4604,6 +4692,7 @@ os_prompt% </pre> <type name="process_info_result_item"/> <type name="stack_item"/> <type name="priority_level"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <desc> <p>Returns information about the process identified by @@ -4696,13 +4785,14 @@ os_prompt% </pre> The content of <c><anno>GCInfo</anno></c> can be changed without prior notice.</p> </item> + <marker id="process_info_garbage_collection_info"/> <tag><c>{garbage_collection_info, <anno>GCInfo</anno>}</c></tag> <item> <p><c><anno>GCInfo</anno></c> is a list containing miscellaneous detailed information about garbage collection for this process. The content of <c><anno>GCInfo</anno></c> can be changed without prior notice. - See <seealso marker="#gc_start">gc_start</seealso> in + See <seealso marker="#gc_minor_start">gc_minor_start</seealso> in <seealso marker="#trace/3">erlang:trace/3</seealso> for details about what each item means. </p> @@ -4875,10 +4965,13 @@ os_prompt% </pre> total suspend count on <c><anno>Suspendee</anno></c>, only the parts contributed by <c><anno>Pid</anno></c>.</p> </item> + <marker id="process_info_total_heap_size"/> <tag><c>{total_heap_size, <anno>Size</anno>}</c></tag> <item> <p><c><anno>Size</anno></c> is the total size, in words, of all heap - fragments of the process. This includes the process stack.</p> + fragments of the process. This includes the process stack and + any unreceived messages that are considered to be part of the + heap. </p> </item> <tag><c>{trace, <anno>InternalTraceFlags</anno>}</c></tag> <item> @@ -5567,6 +5660,7 @@ true</pre> <name name="spawn_opt" arity="2"/> <fsummary>Creates a new process with a fun as entry point.</fsummary> <type name="priority_level"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <type name="spawn_opt_option" /> <desc> @@ -5584,6 +5678,7 @@ true</pre> <name name="spawn_opt" arity="3"/> <fsummary>Creates a new process with a fun as entry point on a given node.</fsummary> <type name="priority_level"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <type name="spawn_opt_option" /> <desc> @@ -5600,6 +5695,7 @@ true</pre> <name name="spawn_opt" arity="4"/> <fsummary>Creates a new process with a function as entry point.</fsummary> <type name="priority_level"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <type name="spawn_opt_option" /> <desc> @@ -5703,13 +5799,23 @@ true</pre> fine-tuning an application and to measure the execution time with various <c><anno>VSize</anno></c> values.</p> </item> + <tag><c>{max_heap_size, <anno>Size</anno>}</c></tag> + <item> + <p>Sets the <c>max_heap_size</c> process flag. The default + <c>max_heap_size</c> is determined by the + <seealso marker="erl#+hmax"><c>+hmax</c></seealso> <c>erl</c> + command line argument. For more information, see the + documentation of + <seealso marker="#process_flag_max_heap_size"><c>process_flag(max_heap_size, + <anno>Size</anno>)</c></seealso>.</p> + </item> <tag><c>{message_queue_data, <anno>MQD</anno>}</c></tag> <item> <p>Sets the state of the <c>message_queue_data</c> process flag. <c><anno>MQD</anno></c> should be either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>. The default <c>message_queue_data</c> process flag is determined by the - <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso> <c>erl</c> + <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso> <c>erl</c> command line argument. For more information, see the documentation of <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data, @@ -5723,6 +5829,7 @@ true</pre> <name name="spawn_opt" arity="5"/> <fsummary>Creates a new process with a function as entry point on a given node.</fsummary> <type name="priority_level"/> + <type name="max_heap_size" /> <type name="message_queue_data" /> <type name="spawn_opt_option" /> <desc> @@ -6504,8 +6611,25 @@ ok </desc> </func> + <marker id="system_flag_max_heap_size"></marker> <func> <name name="system_flag" arity="2" clause_i="8"/> + <type name="max_heap_size"/> + <fsummary>Sets system flag <c>max_heap_size</c></fsummary> + <desc> + <p> + Sets the default maximum heap size settings for processes. + The size is given in words. The new <c>max_heap_size</c> + effects only processes spawned efter the change has been made. + <c>max_heap_size</c> can be set for individual processes using + <seealso marker="#spawn_opt/4">spawn_opt/N</seealso> or + <seealso marker="#process_flag_message_queue_data">process_flag/2</seealso>.</p> + <p>Returns the old value of the flag.</p> + </desc> + </func> + + <func> + <name name="system_flag" arity="2" clause_i="9"/> <fsummary>Sets system flag <c>multi_scheduling</c>.</fsummary> <desc> <p><marker id="system_flag_multi_scheduling"></marker> @@ -6555,7 +6679,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="9"/> + <name name="system_flag" arity="2" clause_i="10"/> <fsummary>Sets system flag <c>scheduler_bind_type</c>.</fsummary> <type name="scheduler_bind_type"/> <desc> @@ -6673,7 +6797,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="10"/> + <name name="system_flag" arity="2" clause_i="11"/> <fsummary>Sets system flag <c>scheduler_wall_time</c>.</fsummary> <desc><p><marker id="system_flag_scheduler_wall_time"></marker> Turns on or off scheduler wall time measurements.</p> @@ -6683,7 +6807,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="11"/> + <name name="system_flag" arity="2" clause_i="12"/> <fsummary>Sets system flag <c>schedulers_online</c>.</fsummary> <desc> <p><marker id="system_flag_schedulers_online"></marker> @@ -6708,7 +6832,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="12"/> + <name name="system_flag" arity="2" clause_i="13"/> <fsummary>Sets system flag <c>trace_control_word</c>.</fsummary> <desc> <p>Sets the value of the node trace control word to @@ -6722,7 +6846,7 @@ ok </func> <func> - <name name="system_flag" arity="2" clause_i="12"/> + <name name="system_flag" arity="2" clause_i="14"/> <fsummary>Finalize the Time Offset</fsummary> <desc> <p><marker id="system_flag_time_offset"></marker> @@ -6989,6 +7113,81 @@ ok </func> <func> + <name name="system_info" arity="1" clause_i="27"/> + <name name="system_info" arity="1" clause_i="28"/> + <name name="system_info" arity="1" clause_i="36"/> + <name name="system_info" arity="1" clause_i="37"/> + <name name="system_info" arity="1" clause_i="38"/> + <name name="system_info" arity="1" clause_i="39"/> + <type name="message_queue_data"/> + <type name="max_heap_size"/> + <fsummary>Information about the default process heap settings.</fsummary> + <desc> + <taglist> + <tag><c>fullsweep_after</c></tag> + <item> + <p>Returns <c>{fullsweep_after, integer() >= 0}</c>, which is + the <c>fullsweep_after</c> garbage collection setting used + by default. For more information, see + <c>garbage_collection</c> described in the following.</p> + </item> + <tag><c>garbage_collection</c></tag> + <item> + <p>Returns a list describing the default garbage collection + settings. A process spawned on the local node by a + <c>spawn</c> or <c>spawn_link</c> uses these + garbage collection settings. The default settings can be + changed by using + <seealso marker="#system_flag/2">system_flag/2</seealso>. + <seealso marker="#spawn_opt/4">spawn_opt/4</seealso> + can spawn a process that does not use the default + settings.</p> + </item> + <tag><c>max_heap_size</c></tag> + <item> + <p>Returns <c>{max_heap_size, <anno>MaxHeapSize</anno>}</c>, + where <c><anno>MaxHeapSize</anno></c> is the current + system-wide max heap size settings for spawned processes. + This setting can be set using the <c>erl</c> command line + flags <seealso marker="erl#+hmax"><c>+hmax</c></seealso>, + <seealso marker="erl#+hmaxk"><c>+hmaxk</c></seealso> and + <seealso marker="erl#+hmaxel"><c>+hmaxel</c></seealso>. It can + also be changed at run-time using + <seealso marker="#system_flag_max_heap_size"> + <c>erlang:system_flag(max_heap_size, MaxHeapSize)</c></seealso>. + For more details about the <c>max_heap_size</c> process flag + see <seealso marker="#process_flag_max_heap_size"> + <c>process_flag(max_heap_size, MaxHeapSize)</c></seealso>. + </p> + </item> + <tag><c>min_heap_size</c></tag> + <item> + <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, + where <c><anno>MinHeapSize</anno></c> is the current + system-wide minimum heap size for spawned processes.</p> + </item> + <tag><marker id="system_info_message_queue_data"><c>message_queue_data</c></marker></tag> + <item> + <p>Returns the default value of the <c>message_queue_data</c> + process flag which is either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>. + This default is set by the <c>erl</c> command line argument + <seealso marker="erl#+hmqd"><c>+hmqd</c></seealso>. For more information on the + <c>message_queue_data</c> process flag, see documentation of + <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data, + MQD)</c></seealso>.</p> + </item> + <tag><c>min_bin_vheap_size</c></tag> + <item> + <p>Returns <c>{min_bin_vheap_size, + <anno>MinBinVHeapSize</anno>}</c>, where + <c><anno>MinBinVHeapSize</anno></c> is the current system-wide + minimum binary virtual heap size for spawned processes.</p> + </item> + </taglist> + </desc> + </func> + + <func> <name name="system_info" arity="1" clause_i="6"/> <name name="system_info" arity="1" clause_i="7"/> <name name="system_info" arity="1" clause_i="8"/> @@ -7008,8 +7207,6 @@ ok <name name="system_info" arity="1" clause_i="24"/> <name name="system_info" arity="1" clause_i="25"/> <name name="system_info" arity="1" clause_i="26"/> - <name name="system_info" arity="1" clause_i="27"/> - <name name="system_info" arity="1" clause_i="28"/> <name name="system_info" arity="1" clause_i="29"/> <name name="system_info" arity="1" clause_i="30"/> <name name="system_info" arity="1" clause_i="31"/> @@ -7017,10 +7214,6 @@ ok <name name="system_info" arity="1" clause_i="33"/> <name name="system_info" arity="1" clause_i="34"/> <name name="system_info" arity="1" clause_i="35"/> - <name name="system_info" arity="1" clause_i="36"/> - <name name="system_info" arity="1" clause_i="37"/> - <name name="system_info" arity="1" clause_i="38"/> - <name name="system_info" arity="1" clause_i="39"/> <name name="system_info" arity="1" clause_i="40"/> <name name="system_info" arity="1" clause_i="41"/> <name name="system_info" arity="1" clause_i="42"/> @@ -7050,6 +7243,7 @@ ok <name name="system_info" arity="1" clause_i="66"/> <name name="system_info" arity="1" clause_i="67"/> <name name="system_info" arity="1" clause_i="68"/> + <name name="system_info" arity="1" clause_i="69"/> <fsummary>Information about the system.</fsummary> <desc> <p>Returns various information about the current system @@ -7286,25 +7480,6 @@ ok <c>ERL_MAX_ETS_TABLES</c> before starting the Erlang runtime system.</p> </item> - <tag><c>fullsweep_after</c></tag> - <item> - <p>Returns <c>{fullsweep_after, integer() >= 0}</c>, which is - the <c>fullsweep_after</c> garbage collection setting used - by default. For more information, see - <c>garbage_collection</c> described in the following.</p> - </item> - <tag><c>garbage_collection</c></tag> - <item> - <p>Returns a list describing the default garbage collection - settings. A process spawned on the local node by a - <c>spawn</c> or <c>spawn_link</c> uses these - garbage collection settings. The default settings can be - changed by using - <seealso marker="#system_flag/2">system_flag/2</seealso>. - <seealso marker="#spawn_opt/4">spawn_opt/4</seealso> - can spawn a process that does not use the default - settings.</p> - </item> <tag><c>heap_sizes</c></tag> <item> <p>Returns a list of integers representing valid heap sizes @@ -7379,29 +7554,6 @@ ok <item> <p>Returns a string containing the Erlang machine name.</p> </item> - <tag><c>min_heap_size</c></tag> - <item> - <p>Returns <c>{min_heap_size, <anno>MinHeapSize</anno>}</c>, - where <c><anno>MinHeapSize</anno></c> is the current - system-wide minimum heap size for spawned processes.</p> - </item> - <tag><marker id="system_info_message_queue_data"><c>message_queue_data</c></marker></tag> - <item> - <p>Returns the default value of the <c>message_queue_data</c> - process flag which is either <c>off_heap</c>, <c>on_heap</c>, or <c>mixed</c>. - This default is set by the <c>erl</c> command line argument - <seealso marker="erl#+xmqd"><c>+xmqd</c></seealso>. For more information on the - <c>message_queue_data</c> process flag, see documentation of - <seealso marker="#process_flag_message_queue_data"><c>process_flag(message_queue_data, - MQD)</c></seealso>.</p> - </item> - <tag><c>min_bin_vheap_size</c></tag> - <item> - <p>Returns <c>{min_bin_vheap_size, - <anno>MinBinVHeapSize</anno>}</c>, where - <c><anno>MinBinVHeapSize</anno></c> is the current system-wide - minimum binary virtual heap size for spawned processes.</p> - </item> <tag><c>modified_timing_level</c></tag> <item> <p>Returns the modified timing-level (an integer) if @@ -7968,7 +8120,7 @@ ok <c>stack_size</c>, <c>mbuf_size</c>, <c>old_heap_size</c>, and <c>old_heap_block_size</c>. These tuples are explained in the description of trace message - <seealso marker="#gc_start">gc_start</seealso> (see + <seealso marker="#gc_minor_start">gc_minor_start</seealso> (see <seealso marker="#trace/3">erlang:trace/3</seealso>). New tuples can be added, and the order of the tuples in the <c>Info</c> list can be changed at any time without @@ -8026,12 +8178,13 @@ ok <c>GcPid</c> and <c>Info</c> are the same as for <c>long_gc</c> earlier, except that the tuple tagged with <c>timeout</c> is not present.</p> - <p>As of <c>ERTS</c> 5.6, the monitor message is sent - if the sum of the sizes of all memory blocks allocated - for all heap generations is equal to or higher than <c>Size</c>. - Previously the monitor message was sent if the memory block - allocated for the youngest generation was equal to or higher - than <c>Size</c>.</p> + <p>The monitor message is sent if the sum of the sizes of + all memory blocks allocated for all heap generations after + a garbage collection is equal to or higher than <c>Size</c>.</p> + <p>When a process is killed by <seealso marker="#process_flag_max_heap_size"> + <c>max_heap_size</c></seealso>, it is killed before the + garbage collection is complete and thus no large heap message + will be sent.</p> </item> <tag><c>busy_port</c></tag> <item> @@ -8558,7 +8711,9 @@ timestamp() -> <tag><c>garbage_collection</c></tag> <item> <p>Traces garbage collections of processes.</p> - <p>Message tags: <c><seealso marker="#trace_3_trace_messages_gc_start">gc_start</seealso></c> and <c><seealso marker="#trace_3_trace_messages_gc_end">gc_end</seealso></c>.</p> + <p>Message tags: <c><seealso marker="#trace_3_trace_messages_gc_minor_start">gc_minor_start</seealso></c>, + <c><seealso marker="#trace_3_trace_messages_gc_max_heap_size">gc_max_heap_size</seealso></c> and + <c><seealso marker="#trace_3_trace_messages_gc_minor_end">gc_minor_end</seealso></c>.</p> </item> <tag><c>timestamp</c></tag> <item> @@ -8639,8 +8794,8 @@ timestamp() -> <p>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 <seealso marker="erl_tracer"> - erl_tracer</seealso> + on how to write a tracer module see + <seealso marker="erts:erl_tracer"><c>erl_tracer</c></seealso> </p> </item> </taglist> @@ -8882,12 +9037,12 @@ timestamp() -> </p> </item> <tag> - <marker id="trace_3_trace_messages_gc_start"></marker> - <c>{trace, Pid, gc_start, Info}</c> + <marker id="trace_3_trace_messages_gc_minor_start"></marker> + <c>{trace, Pid, gc_minor_start, Info}</c> </tag> <item> - <marker id="gc_start"></marker> - <p>Sent when garbage collection is about to be started. + <marker id="gc_minor_start"></marker> + <p>Sent when a young garbage collection is about to be started. <c>Info</c> is a list of two-element tuples, where the first element is a key, and the second is the value. Do not depend on any order of the tuples. @@ -8927,15 +9082,45 @@ timestamp() -> <p>All sizes are in words.</p> </item> <tag> - <marker id="trace_3_trace_messages_gc_end"></marker> - <c>{trace, Pid, gc_end, Info}</c> + <marker id="trace_3_trace_messages_gc_max_heap_size"></marker> + <c>{trace, Pid, gc_max_heap_size, Info}</c> </tag> <item> - <p>Sent when garbage collection is finished. <c>Info</c> - contains the same kind of list as in message <c>gc_start</c>, + <p> + Sent when the <seealso marker="#process_flag_max_heap_size"><c>max_heap_size</c></seealso> + is reached during garbage collection. <c>Info</c> contains the + same kind of list as in message <c>gc_start</c>, + but the sizes reflect the sizes that triggered max_heap_size to + be reached. + </p> + </item> + <tag> + <marker id="trace_3_trace_messages_gc_minor_end"></marker> + <c>{trace, Pid, gc_minor_end, Info}</c> + </tag> + <item> + <p>Sent when young garbage collection is finished. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c>, but the sizes reflect the new sizes after garbage collection.</p> </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_start"></marker> + <c>{trace, Pid, gc_major_start, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is about to be started. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c>.</p> + </item> + <tag> + <marker id="trace_3_trace_messages_gc_major_end"></marker> + <c>{trace, Pid, gc_major_end, Info}</c> + </tag> + <item> + <p>Sent when fullsweep garbage collection is finished. <c>Info</c> + contains the same kind of list as in message <c>gc_minor_start</c> + but the sizes reflect the new sizes after a fullsweep garbage collection.</p> + </item> </taglist> <p>If the tracing process/port dies or the tracer module returns <c>remove</c>, the flags are silently removed.</p> @@ -8991,7 +9176,7 @@ timestamp() -> <c>erlang:trace_delivered(<anno>Tracee</anno>)</c> resides on. The special <c><anno>Tracee</anno></c> atom <c>all</c> denotes all processes that currently are traced in the node.</p> - <p>When used together with an <seealso marker="#erl_tracer"> + <p>When used together with an <seealso marker="erts:erl_tracer"> Tracer Module</seealso> any message sent in the trace callback is guaranteed to have reached it's recipient before the <c>trace_delivered</c> message is sent.</p> @@ -9017,16 +9202,16 @@ timestamp() -> <type name="trace_info_flag"/> <type name="trace_match_spec"/> <desc> - <p>Returns trace information about a port, process or function.</p> - <p>To get information about a port or process, - <c><anno>PidPortOrFunc</anno></c> is to + <p>Returns trace information about a port, process, function or event.</p> + <p><em>To get information about a port or process</em>, + <c><anno>PidPortFuncEvent</anno></c> is to be a process identifier (pid), port identifier or one of the atoms <c>new</c>, <c>new_processes</c>, <c>new_ports</c>. The atom <c>new</c> or <c>new_processes</c> means that the default trace state for processes to be created is returned. The atom <c>new_ports</c> means that the default trace state for ports to be created is returned. </p> - <p>The following <c>Item</c>s are valid:</p> + <p>The following <c>Item</c>s are valid for ports and processes:</p> <taglist> <tag><c>flags</c></tag> <item> @@ -9050,12 +9235,15 @@ timestamp() -> value is <c>[]</c>.</p> </item> </taglist> - <p>To get information about a function, <c><anno>PidPortOrFunc</anno></c> is to + <p><em>To get information about a function</em>, <c><anno>PidPortFuncEvent</anno></c> is to be the three-element tuple <c>{Module, Function, Arity}</c> or the atom <c>on_load</c>. No wild cards are allowed. Returns <c>undefined</c> if the function does not exist, or - <c>false</c> if the function is not traced.</p> - <p>The following <c>Item</c>s are valid::</p> + <c>false</c> if the function is not traced. If <c><anno>PidPortFuncEvent</anno></c> + is <c>on_load</c>, the information returned refers to + the default value for code that will be loaded.</p> + + <p>The following <c>Item</c>s are valid for functions:</p> <taglist> <tag><c>traced</c></tag> <item> @@ -9114,39 +9302,177 @@ timestamp() -> is active for this function.</p> </item> </taglist> + <p><em>To get information about an event</em>, <c><anno>PidPortFuncEvent</anno></c> is to + be one of the atoms <c>send</c> or <c>'receive'</c>.</p> + <p>The only valid <c>Item</c> for events is:</p> + <taglist> + <tag><c>match_spec</c></tag> + <item> + <p>Returns the match specification for this event, if it + has one, or <c>true</c> if no match specification has been + set.</p> + </item> + </taglist> <p>The return value is <c>{<anno>Item</anno>, Value}</c>, where <c>Value</c> is the requested information as described earlier. If a pid for a dead process was given, or the name of a non-existing function, <c>Value</c> is <c>undefined</c>.</p> - <p>If <c><anno>PidPortOrFunc</anno></c> is <c>on_load</c>, the information - returned refers to the default value for code that will be - loaded.</p> </desc> </func> <func> <name name="trace_pattern" arity="2" clause_i="1"/> - <fsummary>Sets trace patterns for global call tracing.</fsummary> + <fsummary>Sets trace patterns for call, send or 'receive' tracing.</fsummary> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> <desc> <p>The same as - <seealso marker="#trace_pattern/3">erlang:trace_pattern(MFA, MatchSpec, [])</seealso>, + <seealso marker="#trace_pattern/3">erlang:trace_pattern(Event, MatchSpec, [])</seealso>, retained for backward compatibility.</p> </desc> </func> <func> - <name name="trace_pattern" arity="3"/> + <name name="trace_pattern" arity="3" clause_i="1"/> + <fsummary>Sets trace pattern for message sending.</fsummary> + <type name="trace_match_spec"/> + <desc> + <p>Sets trace pattern for <em>message sending</em>. + Must be combined with + <seealso marker="#trace/3">erlang:trace/3</seealso> + to set the <c>send</c> trace flag for one or more processes. + By default all messages, sent from <c>send</c> traced processes, + are traced. Use <c>erlang:trace_pattern/3</c> to limit + traced send events based on the message content, the sender + and/or the receiver.</p> + <p>Argument <c><anno>MatchSpec</anno></c> can take the + following forms:</p> + <taglist> + <tag><c><anno>MatchSpecList</anno></c></tag> + <item> + <p>A list of match specifications. The matching is done + on the list <c>[Receiver, Msg]</c>. <c>Receiver</c> + is the process or port identity of the receiver and + <c>Msg</c> is the message term. The pid of the sending + process can be accessed with the guard function + <c>self/0</c>. An empty list is the same as <c>true</c>. + See the users guide section + <seealso marker="erts:match_spec">Match Specifications in Erlang</seealso> + for more information.</p> + </item> + <tag><c>true</c></tag> + <item> + <p>Enables tracing for all sent messages (from <c>send</c> + traced processes). Any match specification is + removed. <em>This is the default</em>.</p> + </item> + <tag><c>false</c></tag> + <item> + <p>Disables tracing for all sent messages. + Any match specification is removed.</p> + </item> + </taglist> + <p>Argument <c><anno>FlagList</anno></c> must be <c>[]</c> + for send tracing.</p> + <p>The return value is always <c>1</c>.</p> + <p>Example; only trace messages to a specific process <c>Pid</c>:</p> + <pre> +> <input>erlang:trace_pattern(send, [{[Pid, '_'],[],[]}], []).</input> +1</pre> + <p>Only trace messages matching <c>{reply, _}</c>:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['_', {reply,'_'}],[],[]}], []).</input> +1</pre> + <p>Only trace messages sent to the sender itself:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['$1', '_'],[{'=:=','$1',{self}}],[]}], []).</input> +1</pre> + <p>Only trace messages sent to other nodes:</p> + <pre> +> <input>erlang:trace_pattern(send, [{['$1', '_'],[{'=/=',{node,'$1'},{node}}],[]}], []).</input> +1</pre> + <note><p>A match specification for <c>send</c> trace can use + all guard and body functions except <c>caller</c>.</p></note> + </desc> + </func> + + <func> + <name name="trace_pattern" arity="3" clause_i="2"/> + <fsummary>Sets trace pattern for tracing of message receiving.</fsummary> + <type name="trace_match_spec"/> + <desc> + <p></p> + <p>Sets trace pattern for <em>message receiving</em>. + Must be combined with + <seealso marker="#trace/3">erlang:trace/3</seealso> + to set the <c>'receive'</c> trace flag for one or more processes. + By default all messages, received by <c>'receive'</c> traced processes, + are traced. Use <c>erlang:trace_pattern/3</c> to limit + traced receive events based on the message content, the sender + and/or the receiver.</p> + <p>Argument <c><anno>MatchSpec</anno></c> can take the + following forms:</p> + <taglist> + <tag><c><anno>MatchSpecList</anno></c></tag> + <item> + <p>A list of match specifications. The matching is done + on the list <c>[Node, Sender, Msg]</c>. <c>Node</c> + is the node name of the sender. <c>Sender</c> is the + process or port identity of the sender, or the atom + <c>undefined</c> if the sender is not known (which may + be the case for remote senders). <c>Msg</c> is the + message term. The pid of the receiving process can be + accessed with the guard function <c>self/0</c>. An empty + list is the same as <c>true</c>. See the users guide section + <seealso marker="erts:match_spec">Match Specifications in Erlang</seealso> + for more information.</p> + </item> + <tag><c>true</c></tag> + <item> + <p>Enables tracing for all received messages (to <c>'receive'</c> + traced processes). Any match specification is + removed. <em>This is the default</em>.</p> + </item> + <tag><c>false</c></tag> + <item> + <p>Disables tracing for all received messages. + Any match specification is removed.</p> + </item> + </taglist> + <p>Argument <c><anno>FlagList</anno></c> must be <c>[]</c> + for receive tracing.</p> + <p>The return value is always <c>1</c>.</p> + <p>Example; only trace messages from a specific process <c>Pid</c>:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['_',Pid, '_'],[],[]}], []).</input> +1</pre> + <p>Only trace messages matching <c>{reply, _}</c>:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['_','_', {reply,'_'}],[],[]}], []).</input> +1</pre> + <p>Only trace messages from other nodes:</p> + <pre> +> <input>erlang:trace_pattern('receive', [{['$1', '_', '_'],[{'=/=','$1',{node}}],[]}], []).</input> +1</pre> + <note><p>A match specification for <c>'receive'</c> trace can + use all guard and body functions except <c>caller, + is_seq_trace, get_seq_token, set_seq_token, enable_trace, + disable_trace, trace, silent</c> and <c>process_dump</c>.</p></note> + </desc> + </func> + + <func> + <name name="trace_pattern" arity="3" clause_i="3"/> <fsummary>Sets trace patterns for tracing of function calls.</fsummary> <type name="trace_pattern_mfa"/> <type name="trace_match_spec"/> <type name="trace_pattern_flag"/> <desc> - <p>Enables or disables call tracing for - one or more functions. Must be combined with + <p>Enables or disables <em>call tracing</em> for one or more functions. + Must be combined with <seealso marker="#trace/3">erlang:trace/3</seealso> - to set the <c>call</c> trace flag for one or more processes.</p> + to set the <c>call</c> trace flag + for one or more processes.</p> <p>Conceptually, call tracing works as follows. Inside the Erlang Virtual Machine, a set of processes and a set of functions are to be traced. If a traced process @@ -9201,7 +9527,8 @@ timestamp() -> </item> <tag><c>true</c></tag> <item> - <p>Enables tracing for the matching functions.</p> + <p>Enables tracing for the matching functions. + Any match specification is removed.</p> </item> <tag><c><anno>MatchSpecList</anno></c></tag> <item> diff --git a/erts/doc/src/match_spec.xml b/erts/doc/src/match_spec.xml index 3944f24f84..7be3d15de6 100644 --- a/erts/doc/src/match_spec.xml +++ b/erts/doc/src/match_spec.xml @@ -33,21 +33,15 @@ <file>match_spec.xml</file> </header> <p>A "match specification" (match_spec) is an Erlang term describing a - small "program" that will try to match something (either the - parameters to a function as used in the <c><![CDATA[erlang:trace_pattern/2]]></c> - BIF, or the objects in an ETS table.). + small "program" that will try to match something. It can be used + to either control tracing with + <seealso marker="erlang#trace_pattern/3">erlang:trace_pattern/3</seealso> + or to search for objects in an ETS table with for example + <seealso marker="stdlib:ets#select/2">ets:select/2</seealso>. The match_spec in many ways works like a small function in Erlang, but is interpreted/compiled by the Erlang runtime system to something much more efficient than calling an Erlang function. The match_spec is also very limited compared to the expressiveness of real Erlang functions.</p> - <p>Match specifications are given to the BIF <c><![CDATA[erlang:trace_pattern/2]]></c> to - execute matching of function arguments as well as to define some actions - to be taken when the match succeeds (the <c><![CDATA[MatchBody]]></c> part). Match - specifications can also be used in ETS, to specify objects to be - returned from an <c><![CDATA[ets:select/2]]></c> call (or other select - calls). The semantics and restrictions differ slightly when using - match specifications for tracing and in ETS, the differences are - defined in a separate paragraph below.</p> <p>The most notable difference between a match_spec and an Erlang fun is of course the syntax. Match specifications are Erlang terms, not Erlang code. A match_spec also has a somewhat strange concept of @@ -382,6 +376,51 @@ the pid() of the current process.</p> </section> + <marker id="match_target"></marker> + <section> + <title>Match target</title> + <p>Each execution of a match specification is done against + a match target term. The format and content of the target term + depends on the context in which the match is done. The match + target for ETS is always a full table tuple. The match target + for call trace is always a list of all function arguments. The + match target for event trace depends on the event type, see + table below.</p> + <table> + <row> + <cell align="left" valign="middle">Context</cell> + <cell align="left" valign="middle">Type</cell> + <cell align="left" valign="middle">Match target</cell> + <cell align="left" valign="middle">Description</cell> + </row> + <row> + <cell align="left" valign="middle">ETS</cell> + <cell align="left" valign="middle"></cell> + <cell align="left" valign="middle">{Key, Value1, Value2, ...}</cell> + <cell align="left" valign="middle">A table object</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">call</cell> + <cell align="left" valign="middle">[Arg1, Arg2, ...]</cell> + <cell align="left" valign="middle">Function arguments</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">send</cell> + <cell align="left" valign="middle">[Receiver, Message]</cell> + <cell align="left" valign="middle">Receiving process/port and message term</cell> + </row> + <row> + <cell align="left" valign="middle">Trace</cell> + <cell align="left" valign="middle">'receive'</cell> + <cell align="left" valign="middle">[Node, Sender, Message]</cell> + <cell align="left" valign="middle">Sending node, process/port and message term</cell> + </row> + <tcaption>Match target depending on context</tcaption> + </table> + </section> + <section> <title>Variables and literals</title> <p>Variables take the form <c><![CDATA['$<number>']]></c> where @@ -396,10 +435,8 @@ <c><![CDATA[MatchCondition]]></c> parts, only variables bound previously may be used. As a special case, in the <c><![CDATA[MatchCondition/MatchBody]]></c> parts, the variable <c><![CDATA['$_']]></c> - expands to the whole expression which matched the - <c><![CDATA[MatchHead]]></c> (i.e., the whole parameter list to the possibly - traced function or the whole matching object in the ets table) - and the variable <c><![CDATA['$$']]></c> expands to a list + expands to the whole <seealso marker="#match_target">match target</seealso> + term and the variable <c><![CDATA['$$']]></c> expands to a list of the values of all bound variables in order (i.e. <c><![CDATA[['$1','$2', ...]]]></c>). </p> @@ -480,8 +517,8 @@ <p>For each tuple in the <c><![CDATA[MatchExpression]]></c> list and while no match has succeeded:</p> <list type="bulleted"> - <item>Match the <c><![CDATA[MatchHead]]></c> part against the arguments to the - function, + <item>Match the <c><![CDATA[MatchHead]]></c> part against the + match target term, binding the <c><![CDATA['$<number>']]></c> variables (much like in <c><![CDATA[ets:match/2]]></c>). If the <c><![CDATA[MatchHead]]></c> cannot match the arguments, the match fails. @@ -522,13 +559,10 @@ term. The <c><![CDATA[ActionTerm]]></c>'s are executed as in an imperative language, i.e. for their side effects. Functions with side effects are also allowed when tracing.</p> - <p>In ETS the match head is a <c><![CDATA[tuple()]]></c> (or a single match - variable) while it is a list (or a single match variable) when - tracing.</p> </section> <section> - <title>ETS Examples</title> + <title>Tracing Examples</title> <p>Match an argument list of three where the first and third arguments are equal:</p> <code type="none"><![CDATA[ @@ -585,42 +619,6 @@ parameter list with a single variable is a special case. In all other cases the <c><![CDATA[MatchHead]]></c> has to be a <em>proper</em> list. </p> - <p>Match all objects in an ets table where the first element is - the atom 'strider' and the tuple arity is 3 and return the whole - object.</p> - <code type="none"><![CDATA[ -[{{strider,'_','_'}, - [], - ['$_']}] - ]]></code> - <p>Match all objects in an ets table with arity > 1 and the first - element is 'gandalf', return element 2.</p> - <code type="none"><![CDATA[ -[{'$1', - [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}], - [{element,2,'$1'}]}] - ]]></code> - <p>In the above example, if the first element had been the key, - it's much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> - part than in the <c><![CDATA[MatchConditions]]></c> part. The search space of - the tables is restricted with regards to the <c><![CDATA[MatchHead]]></c> so - that only objects with the matching key are searched. - </p> - <p>Match tuples of 3 elements where the second element is either - 'merry' or 'pippin', return the whole objects.</p> - <code type="none"><![CDATA[ -[{{'_',merry,'_'}, - [], - ['$_']}, - {{'_',pippin,'_'}, - [], - ['$_']}] - ]]></code> - <p>The function <c><![CDATA[ets:test_ms/2]]></c> can be useful for testing - complicated ets matches.</p> - </section> - <section> - <title>Tracing Examples</title> <p>Only generate trace message if trace control word is set to 1:</p> <code type="none"><![CDATA[ [{'_', @@ -658,5 +656,42 @@ {'_',[],[]}] ]]></code> </section> + + <section> + <title>ETS Examples</title> + <p>Match all objects in an ets table where the first element is + the atom 'strider' and the tuple arity is 3 and return the whole + object.</p> + <code type="none"><![CDATA[ +[{{strider,'_','_'}, + [], + ['$_']}] + ]]></code> + <p>Match all objects in an ets table with arity > 1 and the first + element is 'gandalf', return element 2.</p> + <code type="none"><![CDATA[ +[{'$1', + [{'==', gandalf, {element, 1, '$1'}},{'>=',{size, '$1'},2}], + [{element,2,'$1'}]}] + ]]></code> + <p>In the above example, if the first element had been the key, + it's much more efficient to match that key in the <c><![CDATA[MatchHead]]></c> + part than in the <c><![CDATA[MatchConditions]]></c> part. The search space of + the tables is restricted with regards to the <c><![CDATA[MatchHead]]></c> so + that only objects with the matching key are searched. + </p> + <p>Match tuples of 3 elements where the second element is either + 'merry' or 'pippin', return the whole objects.</p> + <code type="none"><![CDATA[ +[{{'_',merry,'_'}, + [], + ['$_']}, + {{'_',pippin,'_'}, + [], + ['$_']}] + ]]></code> + <p>The function <c><![CDATA[ets:test_ms/2]]></c> can be useful for testing + complicated ets matches.</p> + </section> </chapter> |