diff options
Diffstat (limited to 'erts/doc')
-rw-r--r-- | erts/doc/src/Makefile | 1 | ||||
-rw-r--r-- | erts/doc/src/communication.xml | 89 | ||||
-rw-r--r-- | erts/doc/src/driver_entry.xml | 16 | ||||
-rw-r--r-- | erts/doc/src/erl.xml | 103 | ||||
-rw-r--r-- | erts/doc/src/erl_driver.xml | 185 | ||||
-rw-r--r-- | erts/doc/src/erlang.xml | 338 | ||||
-rw-r--r-- | erts/doc/src/part.xml | 1 |
7 files changed, 598 insertions, 135 deletions
diff --git a/erts/doc/src/Makefile b/erts/doc/src/Makefile index 91e823fdb1..89d7c85a86 100644 --- a/erts/doc/src/Makefile +++ b/erts/doc/src/Makefile @@ -77,6 +77,7 @@ XML_CHAPTER_FILES = \ inet_cfg.xml \ erl_ext_dist.xml \ erl_dist_protocol.xml \ + communication.xml \ notes.xml \ notes_history.xml diff --git a/erts/doc/src/communication.xml b/erts/doc/src/communication.xml new file mode 100644 index 0000000000..6049123f6a --- /dev/null +++ b/erts/doc/src/communication.xml @@ -0,0 +1,89 @@ +<?xml version="1.0" encoding="latin1" ?> +<!DOCTYPE chapter SYSTEM "chapter.dtd"> + +<chapter> + <header> + <copyright> + <year>2012</year><year>2012</year> + <holder>Ericsson AB. All Rights Reserved.</holder> + </copyright> + <legalnotice> + The contents of this file are subject to the Erlang Public License, + Version 1.1, (the "License"); you may not use this file except in + compliance with the License. You should have received a copy of the + Erlang Public License along with this software. If not, it can be + retrieved online at http://www.erlang.org/. + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + the License for the specific language governing rights and limitations + under the License. + + </legalnotice> + + <title>Communication in Erlang</title> + <prepared>Rickard Green</prepared> + <responsible></responsible> + <docno></docno> + <approved></approved> + <checked></checked> + <date>2012-12-03</date> + <rev>PA1</rev> + <file>communication.xml</file> + </header> + <p>Communication in Erlang is conceptually performed using + asynchronous signaling. All different executing entities + such as processes, and ports communicate via asynchronous + signals. The most commonly used signal is a message. Other + common signals are exit, link, unlink, monitor, demonitor + signals.</p> + <section> + <title>Passing of Signals</title> + <p>The amount of time that passes between a signal being 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 + signal originated from. When communicating over the distribution, + signals may be lost if the distribution channel goes down.</p> + <p>The only signal ordering guarantee given is the following. If + an entity sends multiple signals to the same destination entity, + the order will be preserved. That is, if <c>A</c> send + a signal <c>S1</c> to <c>B</c>, and later sends + the signal <c>S2</c> to <c>B</c>, <c>S1</c> is guaranteed not to + arrive after <c>S2</c>.</p> + </section> + <section> + <title>Synchronous Communication</title> + <p>Some communication is synchronous. If broken down into pieces, + a synchronous communication operation, consists of two asynchronous + signals. One request signal and one reply signal. An example of + such a synchronous communication is a call to <c>process_info/2</c> + when the first argument is not <c>self()</c>. The caller will send + an asynchronous signal requesting information, and will then + wait for the reply signal containing the requested information. When + the request signal reaches its destination the destination process + replies with the requested information.</p> + </section> + <section> + <title>Implementation</title> + <p>The implementation of different asynchronous signals in the + VM may vary over time, but the behavior will always respect this + concept of asynchronous signals being passed between entities + as described above.</p> + <p>By inspecting the implementation you might notice that some + specific signal actually gives a stricter guarantee than described + above. It is of vital importance that such knowledge about the + implementation is <em>not</em> used by Erlang code, since the + implementation might change at any time without prior notice.</p> + <p>Some example of major implementation changes:</p> + <list type="bulleted"> + <item>As of ERTS version 5.5.2 exit signals to processes are truly + asynchronously delivered.</item> + <item>As of ERTS version 5.10 all signals from processes to ports + are truly asynchronously delivered.</item> + </list> + </section> +</chapter> + diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index f31b0cb18b..c37138e7b1 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -400,11 +400,11 @@ typedef struct erl_drv_entry { <tag><marker id="driver_flags"/>int driver_flags</tag> <item> - <p>This field is used to pass driver capability information to the - runtime system. If the <c>extended_marker</c> field equals - <c>ERL_DRV_EXTENDED_MARKER</c>, it should contain <c>0</c> or - driver flags (<c>ERL_DRV_FLAG_*</c>) ored bitwise. Currently - the following driver flags exist: + <p>This field is used to pass driver capability and other + information to the runtime system. If the + <c>extended_marker</c> field equals <c>ERL_DRV_EXTENDED_MARKER</c>, + it should contain <c>0</c> or driver flags (<c>ERL_DRV_FLAG_*</c>) + ored bitwise. Currently the following driver flags exist: </p> <taglist> <tag><c>ERL_DRV_FLAG_USE_PORT_LOCKING</c></tag> @@ -427,6 +427,12 @@ typedef struct erl_drv_entry { by the Erlang distribution (the behaviour has always been required by drivers used by the distribution). </item> + <tag><c>ERL_DRV_FLAG_NO_BUSY_MSGQ</c></tag> + <item>Disable busy port message queue functionality. For + more information, see the documentation of the + <seealso marker="erl_driver#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso> + function. + </item> </taglist> </item> <tag>void *handle2</tag> diff --git a/erts/doc/src/erl.xml b/erts/doc/src/erl.xml index 7cdb3a4dfe..99f2466d79 100644 --- a/erts/doc/src/erl.xml +++ b/erts/doc/src/erl.xml @@ -582,13 +582,71 @@ <seealso marker="erts_alloc">erts_alloc(3)</seealso> for further information.</p> </item> + <tag><c><![CDATA[+n Behavior]]></c></tag> + <item> + <p>Control behavior of signals to ports.</p> + <p>As of OTP-R16 signals to ports are truly asynchronously + delivered. Note that signals always have been documented as + asynchronous. The underlying implementation has, however, + previously delivered these signals synchronously. Correctly + written Erlang programs should be able to handle this without + any issues. Bugs in existing Erlang programs that make false + assumptions about signals to ports may, however, be tricky to + find. This switch has been introduced in order to at least + make it easier to compare behaviors during a transition period. + Note that <em>this flag is deprecated</em> as of its + introduction, and is scheduled for removal in OTP-R17. + <c>Behavior</c> should be one of the following characters:</p> + <taglist> + <tag><c>d</c></tag> + <item>The default. Asynchronous signals. A process that sends + a signal to a port may continue execution before the signal + has been delivered to the port.</item> + <tag><c>s</c></tag> + <item>Synchronous signals. A processes that sends a signal + to a port will not continue execution until the signal has + been delivered. Should <em>only</em> be used for testing and + debugging.</item> + <tag><c>a</c></tag> + <item>Asynchronous signals. As the default, but a processes + that sends a signal will even more frequently continue + execution before the signal has been delivered to the + port. Should <em>only</em> be used for testing and + debugging.</item> + </taglist> + </item> <tag><marker id="max_processes"><c><![CDATA[+P Number]]></c></marker></tag> <item> - <p>Sets the maximum number of concurrent processes for this - system. <c><![CDATA[Number]]></c> must be in the range 16..134217727. - Default is 32768.</p> - <p><em>NOTE</em>: It is possible to choose any value in the range - but powers of 2 perform best.</p> + <p>Sets the maximum number of simultaneously existing processes for this + system. Valid range for <c>Number</c> is <c>[1024-134217727]</c></p> + <p><em>NOTE</em>: The actual maximum chosen may be much larger than + the <c>Number</c> 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 + <seealso marker="erlang#system_info_process_limit">erlang:system_info(process_limit)</seealso>.</p> + <p>The default value is <c>262144</c></p> + </item> + <tag><marker id="max_ports"><c><![CDATA[+Q Number]]></c></marker></tag> + <item> + <p>Sets the maximum number of simultaneously existing ports for this + system. Valid range for <c>Number</c> is <c>[1024-134217727]</c></p> + <p><em>NOTE</em>: The actual maximum chosen may be much larger than + the actual <c>Number</c> 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 + <seealso marker="erlang#system_info_port_limit">erlang:system_info(port_limit)</seealso>.</p> + <p>The default value used is normally <c>65536</c>. 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 <c>65536</c>, the chosen value will increased to a value + larger or equal to the maximum amount of file descriptors that + can be opened.</p> + <p>Previously the environment variable <c>ERL_MAX_PORTS</c> was used + for setting the maximum number of simultaneously existing ports. This + environment variable is deprecated, and scheduled for removal in + OTP-R17, but can still be used.</p> </item> <tag><marker id="compat_rel"><c><![CDATA[+R ReleaseNumber]]></c></marker></tag> <item> @@ -597,21 +655,14 @@ default. This flags sets the emulator in compatibility mode with an earlier Erlang/OTP release <c><![CDATA[ReleaseNumber]]></c>. The release number must be in the range - <c><![CDATA[7..<current release>]]></c>. This limits the emulator, - making it possible for it to communicate with Erlang nodes - (as well as C- and Java nodes) running that earlier release.</p> - <p>For example, an R10 node is not automatically compatible - with an R9 node, but R10 nodes started with the <c><![CDATA[+R 9]]></c> - flag can co-exist with R9 nodes in the same distributed - Erlang system, they are R9-compatible.</p> + <c><![CDATA[<current release>-2..<current release>]]></c>. This + limits the emulator, making it possible for it to communicate + with Erlang nodes (as well as C- and Java nodes) running that + earlier release.</p> <p>Note: Make sure all nodes (Erlang-, C-, and Java nodes) of a distributed Erlang system is of the same Erlang/OTP release, or from two different Erlang/OTP releases X and Y, where <em>all</em> Y nodes have compatibility mode X.</p> - <p>For example: A distributed Erlang system can consist of - R10 nodes, or of R9 nodes and R9-compatible R10 nodes, but - not of R9 nodes, R9-compatible R10 nodes and "regular" R10 - nodes, as R9 and "regular" R10 nodes are not compatible.</p> </item> <tag><c><![CDATA[+r]]></c></tag> <item> @@ -934,6 +985,22 @@ without prior notice. </p> </item> + <tag><marker id="+spp"><c>+spp Bool</c></marker></tag> + <item> + <p>Set default scheduler hint for port parallelism. If set to + <c>true</c>, the VM will schedule port tasks when it by this can + improve the parallelism in the system. If set to <c>false</c>, + the VM will try to perform port tasks immediately and by this + improve latency at the expense of parallelism. If this + flag has not been passed, the default scheduler hint for port + parallelism is currently <c>false</c>. The default used can be + inspected in runtime by calling + <seealso marker="erlang#system_info_port_parallelism">erlang:system_info(port_parallelism)</seealso>. + The default can be overriden on port creation by passing the + <seealso marker="erlang#open_port_parallelism">parallelism</seealso> + option to + <seealso marker="erlang#open_port/2">open_port/2</seealso></p>. + </item> <tag><marker id="sched_thread_stack_size"><c><![CDATA[+sss size]]></c></marker></tag> <item> <p>Suggested stack size, in kilowords, for scheduler threads. @@ -1074,7 +1141,7 @@ </item> </taglist> </item> - <tag><c><![CDATA[ERL_AFLAGS]]></c></tag> + <tag><marker id="ERL_AFLAGS"><c><![CDATA[ERL_AFLAGS]]></c></marker></tag> <item> <p>The content of this environment variable will be added to the beginning of the command line for <c><![CDATA[erl]]></c>.</p> @@ -1084,7 +1151,7 @@ the <c><![CDATA[-extra]]></c> section, i.e. the end of the command line following after an <c><![CDATA[-extra]]></c> flag.</p> </item> - <tag><c><![CDATA[ERL_ZFLAGS]]></c> and <c><![CDATA[ERL_FLAGS]]></c></tag> + <tag><marker id="ERL_ZFLAGS"><c><![CDATA[ERL_ZFLAGS]]></c></marker> and <marker id="ERL_FLAGS"><c><![CDATA[ERL_FLAGS]]></c></marker></tag> <item> <p>The content of these environment variables will be added to the end of the command line for <c><![CDATA[erl]]></c>.</p> diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index e16fd744c0..13f42a74a7 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -145,12 +145,20 @@ different threads. This, however, is not a problem for any function in this API, since the emulator has control over these threads.</p> - <note> - <p>Functions not explicitly documented as thread-safe are - <em>not</em> thread-safe. Also note that some functions + <warning> + <p>Functions not explicitly documented as thread safe are + <em>not</em> thread safe. Also note that some functions are <em>only</em> thread safe when used in a runtime system with SMP support.</p> - </note> + <p>A function not explicitly documented as thread safe may at + some point in time have a thread safe implementation in the + runtime system. Such an implementation may however change to + a thread <em>unsafe</em> implementation at any time <em>without + any notice</em> at all. + </p> + <p><em>Only use functions explicitly documented as thread safe + from arbitrary threads.</em></p> + </warning> <p><marker id="lengthy_work"/> As mentioned in the <seealso marker="#WARNING">warning</seealso> text at the beginning of this document it is of vital importance that a driver callback @@ -1529,16 +1537,81 @@ typedef struct ErlIOVec { </desc> </func> <func> + <name><ret>void</ret><nametext>erl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high)</nametext></name> + <fsummary>Set and get limits for busy port message queue</fsummary> + <desc> + <marker id="erl_drv_busy_msgq_limits"></marker> + <p>Sets and gets limits that will be used for controling the + busy state of the port message queue.</p> + <p>The port message queue will be set into a busy + state when the amount of command data queued on the + message queue reaches the <c>high</c> limit. The port + message queue will be set into a not busy state when the + amount of command data queued on the message queue falls + below the <c>low</c> limit. Command data is in this + context data passed to the port using either + <c>Port ! {Owner, {command, Data}}</c>, or + <c>port_command/[2,3]</c>. Note that these limits + only concerns command data that have not yet reached the + port. The <seealso marker="#set_busy_port">busy port</seealso> + feature can be used for data that has reached the port.</p> + + <p>Valid limits are values in the range + <c>[ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]</c>. + Limits will be automatically adjusted to be sane. That is, + the system will adjust values so that the low limit used is + lower or equal to the high limit used. By default the high + limit will be 8 kB and the low limit will be 4 kB.</p> + + <p>By passing a pointer to an integer variable containing + the value <c>ERL_DRV_BUSY_MSGQ_READ_ONLY</c>, currently used + limit will be read and written back to the integer variable. + A new limit can be set by passing a pointer to an integer + variable containing a valid limit. The passed value will be + written to the internal limit. The internal limit will then + be adjusted. After this the adjusted limit will be written + back to the integer variable from which the new value was + read. Values are in bytes.</p> + + <p>The busy message queue feature can be disabled either + by setting the <c>ERL_DRV_FLAG_NO_BUSY_MSGQ</c> + <seealso marker="driver_entry#driver_flags">driver flag</seealso> + in the <seealso marker="driver_entry">driver_entry</seealso> + used by the driver, or by calling this function with + <c>ERL_DRV_BUSY_MSGQ_DISABLED</c> as a limit (either low or + high). When this feature has been disabled it cannot be + enabled again. When reading the limits both of them + will be <c>ERL_DRV_BUSY_MSGQ_DISABLED</c>, if this + feature has been disabled.</p> + + <p>Processes sending command data to the port will be suspended + if either the port is busy or if the port message queue is + busy. Suspended processes will be resumed when neither the + port is busy, nor the port message queue is busy.</p> + + <p>For information about busy port functionality + see the documentation of the + <seealso marker="#set_busy_port">set_busy_port()</seealso> + function.</p> + </desc> + </func> + <func> <name><ret>void</ret><nametext>set_busy_port(ErlDrvPort port, int on)</nametext></name> <fsummary>Signal or unsignal port as busy</fsummary> <desc> <marker id="set_busy_port"></marker> - <p>This function set and resets the busy status of the port. If - <c>on</c> is 1, the port is set to busy, if it's 0 the port - is set to not busy.</p> - <p>When the port is busy, sending to it with <c>Port ! Data</c> - or <c>port_command/2</c>, will block the port owner process, - until the port is signaled as not busy.</p> + <p>This function set and unset the busy state of the port. If + <c>on</c> is non-zero, the port is set to busy, if it's zero the port + is set to not busy. You typically want to combine + this feature with the <seealso marker="#erl_drv_busy_msgq_limits">busy + port message queue</seealso> functionality.</p> + <p>Processes sending command data to the port will be suspended + if either the port is busy or if the port message queue + is busy. Suspended processes will be resumed when neither the + port is busy, nor the port message queue is busy. Command data + is in this context data passed to the port using either + <c>Port ! {Owner, {command, Data}}</c>, or + <c>port_command/[2,3]</c>.</p> <p>If the <seealso marker="driver_entry#driver_flags"><![CDATA[ERL_DRV_FLAG_SOFT_BUSY]]></seealso> has been set in the @@ -1547,6 +1620,10 @@ typedef struct ErlIOVec { <seealso marker="erlang#port_command/3">port_command(Port, Data, [force])</seealso> even though the driver has signaled that it is busy. </p> + <p>For information about busy port message queue functionality + see the documentation of the + <seealso marker="#erl_drv_busy_msgq_limits">erl_drv_busy_msgq_limits()</seealso> + function.</p> </desc> </func> <func> @@ -1607,6 +1684,8 @@ typedef struct ErlIOVec { <desc> <marker id="driver_connected"></marker> <p>This function returns the port owner process.</p> + <p>Note that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> <func> @@ -1634,22 +1713,32 @@ typedef struct ErlIOVec { <tag><seealso marker="driver_entry#call">call</seealso></tag> <item>Called from <c>erlang:port_call/3</c></item> </taglist> + <p>Note that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n)</nametext></name> + <name><ret>int</ret><nametext>erl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n)</nametext></name> <fsummary>Send term data from driver to port owner</fsummary> <desc> - <marker id="driver_output_term"></marker> + <marker id="erl_drv_output_term"></marker> <p>This functions sends data in the special driver term - format. This is a fast way to deliver term data from a - driver. It also needs no binary conversion, so the port - owner process receives data as normal Erlang terms.</p> + format to the port owner process. This is a fast way to + deliver term data from a driver. It also needs no binary + conversion, so the port owner process receives data as + normal Erlang terms. The + <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> + functions can be used for sending to any arbitrary process + on the local node.</p> + <note><p>Note that the <c>port</c> parameter is <em>not</em> + an ordinary port handle, but a port handle converted using + <c>driver_mk_port()</c>.</p></note> <p>The <c>term</c> parameter points to an array of <c>ErlDrvTermData</c>, with <c>n</c> elements. This array contains terms described in the driver term format. Every term consists of one to four elements in the array. The - term first has a term type, and then arguments.</p> + term first has a term type, and then arguments. The + <c>port</c> parameter specifies the sending port.</p> <p>Tuple and lists (with the exception of strings, see below), are built in reverse polish notation, so that to build a tuple, the elements are given first, and then the tuple @@ -1701,17 +1790,17 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len ErlDrvPort port = ... ErlDrvTermData spec[] = { ERL_DRV_ATOM, driver_mk_atom("tcp"), - ERL_DRV_PORT, driver_mk_port(port), + ERL_DRV_PORT, driver_mk_port(drvport), ERL_DRV_INT, 100, ERL_DRV_BINARY, bin, 50, 0, ERL_DRV_LIST, 2, ERL_DRV_TUPLE, 3, }; - driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]> </code> <p>Where <c>bin</c> is a driver binary of length at least 50 - and <c>port</c> is a port handle. Note that the <c>ERL_DRV_LIST</c> + and <c>drvport</c> is a port handle. Note that the <c>ERL_DRV_LIST</c> comes after the elements of the list, likewise the <c>ERL_DRV_TUPLE</c>.</p> <p>The term <c>ERL_DRV_STRING_CONS</c> is a way to construct @@ -1732,7 +1821,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len ERL_DRV_NIL, ERL_DRV_LIST, 4 }; - driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> <p></p> <code type="none"><![CDATA[ @@ -1742,7 +1831,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len ERL_DRV_STRING_CONS, (ErlDrvTermData)"123", 3, ERL_DRV_STRING_CONS, (ErlDrvTermData)"abc", 3, }; - driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> <p>The <c>ERL_DRV_EXT2TERM</c> term type is used for passing a term encoded with the @@ -1762,7 +1851,7 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len ERL_DRV_EXT2TERM, (ErlDrvTermData) binp->orig_bytes, binp->orig_size ERL_DRV_TUPLE, 2, }; - driver_output_term(port, spec, sizeof(spec) / sizeof(spec[0])); + erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); ]]></code> <p>If you want to pass a binary and don't already have the content of the binary in an <c>ErlDrvBinary</c>, you can benefit from using @@ -1778,6 +1867,22 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <c>ERL_DRV_EXT2TERM</c> term types were introduced in the 5.6 version of erts. </p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data from driver to port owner</fsummary> + <desc> + <marker id="driver_output_term"></marker> + <warning><p><c>driver_output_term()</c> is deferred and will + be removed in the OTP-R17 release. Use + <seealso marker="#erl_drv_send_term">erl_drv_output_term()</seealso> + instead.</p> + </warning> + <p>The parameters <c>term</c> and <c>n</c> do the same thing + as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> <p>Note that this function is <em>not</em> thread-safe, not even when the emulator with SMP support is used.</p> </desc> @@ -1791,6 +1896,8 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <c>string</c>. The atom is created and won't change, so the return value may be saved and reused, which is faster than looking up the atom several times.</p> + <p>Note that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> <func> @@ -1799,20 +1906,46 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len <desc> <marker id="driver_mk_port"></marker> <p>This function converts a port handle to the erlang term - format, usable in the <c>driver_output_send</c> function.</p> + format, usable in the <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>, and <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> functions.</p> + <p>Note that this function is <em>not</em> thread-safe, not + even when the emulator with SMP support is used.</p> </desc> </func> <func> - <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> + <name><ret>int</ret><nametext>erl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> <fsummary>Send term data to other process than port owner process</fsummary> <desc> - <marker id="driver_send_term"></marker> + <marker id="erl_drv_send_term"></marker> <p>This function is the only way for a driver to send data to <em>other</em> processes than the port owner process. The <c>receiver</c> parameter specifies the process to receive the data.</p> + <note><p>Note that the <c>port</c> parameter is <em>not</em> + an ordinary port handle, but a port handle converted using + <c>driver_mk_port()</c>.</p></note> + <p>The parameters <c>port</c>, <c>term</c> and <c>n</c> do the same thing + as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> + <p>This function is only thread-safe when the emulator with SMP + support is used.</p> + </desc> + </func> + <func> + <name><ret>int</ret><nametext>driver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n)</nametext></name> + <fsummary>Send term data to other process than port owner process</fsummary> + <desc> + <marker id="driver_send_term"></marker> + <warning><p><c>driver_send_term()</c> is deferred and will + be removed in the OTP-R17 release. Use + <seealso marker="#erl_drv_send_term">erl_drv_send_term()</seealso> + instead.</p> + <p>Also note that parameters of <c>driver_send_term()</c> + cannot be properly checked by the runtime system when + executed by arbitrary threads. This may cause the + <c>driver_send_term()</c> function not to fail when + it should.</p> + </warning> <p>The parameters <c>term</c> and <c>n</c> do the same thing - as in <seealso marker="#driver_output_term">driver_output_term</seealso>.</p> + as in <seealso marker="#erl_drv_output_term">erl_drv_output_term()</seealso>.</p> <p>This function is only thread-safe when the emulator with SMP support is used.</p> </desc> diff --git a/erts/doc/src/erlang.xml b/erts/doc/src/erlang.xml index 5002c48ca1..1a97a84b42 100644 --- a/erts/doc/src/erlang.xml +++ b/erts/doc/src/erlang.xml @@ -854,10 +854,10 @@ b</pre> </func> <func> <name name="exit" arity="2"/> - <fsummary>Send an exit signal to a process</fsummary> + <fsummary>Send an exit signal to a process or a port</fsummary> <desc> <p>Sends an exit signal with exit reason <c><anno>Reason</anno></c> to - the process <c><anno>Pid</anno></c>.</p> + the process or port identified by <c><anno>Pid</anno></c>.</p> <p>The following behavior apply if <c><anno>Reason</anno></c> is any term except <c>normal</c> or <c>kill</c>:</p> <p>If <c><anno>Pid</anno></c> is not trapping exits, <c><anno>Pid</anno></c> itself will @@ -2760,6 +2760,18 @@ os_prompt% </pre> console window when spawning the port program. (This option has no effect on other platforms.)</p> </item> + <tag><marker id="open_port_parallelism"><c>{parallelism, Boolean}</c></marker></tag> + <item> + <p>Set scheduler hint for port parallelism. If set to <c>true</c>, + the VM will schedule port tasks when it by this can improve the + parallelism in the system. If set to <c>false</c>, the VM will + try to perform port tasks immediately and by this improving the + latency at the expense of parallelism. The default can be set on + system startup by passing the + <seealso marker="erl#+spp">+spp</seealso> command line argument + to <seealso marker="erl">erl(1)</seealso>. + </p> + </item> </taglist> <p>The default is <c>stream</c> for all types of port and <c>use_stdio</c> for spawned ports.</p> @@ -2812,10 +2824,11 @@ os_prompt% </pre> the owning process using signals of the form <c>{'EXIT', Port, PosixCode}</c>. See <c>file(3)</c> for possible values of <c>PosixCode</c>.</p> - <p><marker id="ERL_MAX_PORTS"></marker> - The maximum number of ports that can be open at the same - time is 1024 by default, but can be configured by - the environment variable <c>ERL_MAX_PORTS</c>.</p> + <p>The maximum number of ports that can be open at the same + time can be configured by passing the + <seealso marker="erl#max_ports"><c>+Q</c></seealso> + command line flag to + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> </desc> </func> <func> @@ -2873,10 +2886,10 @@ os_prompt% </pre> <desc> <p>Closes an open port. Roughly the same as <c><anno>Port</anno> ! {self(), close}</c> except for the error behaviour - (see below), and that the port does <em>not</em> reply with - <c>{Port, closed}</c>. Any process may close a port with - <c>port_close/1</c>, not only the port owner (the connected - process).</p> + (see below), being synchronous, and that the port does + <em>not</em> reply with <c>{Port, closed}</c>. Any process may + close a port with <c>port_close/1</c>, not only the port owner + (the connected process).</p> <p>For comparison: <c><anno>Port</anno> ! {self(), close}</c> fails with <c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to (i.e., <c><anno>Port</anno></c> refers neither to a port nor to a process). If @@ -2888,8 +2901,12 @@ os_prompt% </pre> <p>Note that any process can close a port using <c><anno>Port</anno> ! {PortOwner, close}</c> just as if it itself was the port owner, but the reply always goes to the port owner.</p> - <p>In short: <c>port_close(Port)</c> has a cleaner and more - logical behaviour than <c><anno>Port</anno> ! {self(), close}</c>.</p> + <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, close}</c> is truly + asynchronous. Note that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_close/1</c> is + however still fully synchronous. This due to its error + behavior.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port or the registered name of an open port.</p> </desc> @@ -2899,11 +2916,11 @@ os_prompt% </pre> <fsummary>Send data to a port</fsummary> <desc> <p>Sends data to a port. Same as - <c><anno>Port</anno> ! {self(), {command, Data}}</c> except for the error - behaviour (see below). Any process may send data to a port - with <c>port_command/2</c>, not only the port owner - (the connected process).</p> - <p>For comparison: <c><anno>Port</anno> ! {self(), {command, Data}}</c> + <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> except for the error + behaviour and being synchronous (see below). Any process may + send data to a port with <c>port_command/2</c>, not only the + port owner (the connected process).</p> + <p>For comparison: <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> fails with <c>badarg</c> if <c><anno>Port</anno></c> cannot be sent to (i.e., <c><anno>Port</anno></c> refers neither to a port nor to a process). If <c><anno>Port</anno></c> is a closed port the data message disappears @@ -2914,11 +2931,14 @@ os_prompt% </pre> <p>Note that any process can send to a port using <c><anno>Port</anno> ! {PortOwner, {command, <anno>Data</anno>}}</c> just as if it itself was the port owner.</p> - <p>In short: <c>port_command(<anno>Port</anno>, <anno>Data</anno>)</c> has a cleaner and - more logical behaviour than - <c><anno>Port</anno> ! {self(), {command, Data}}</c>.</p> <p>If the port is busy, the calling process will be suspended until the port is not busy anymore.</p> + <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, {command, Data}}</c> is + truly asynchronous. Note that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_command/2</c> is + however still fully synchronous. This due to its error + behavior.</p> <p>Failures:</p> <taglist> <tag><c>badarg</c></tag> @@ -2992,7 +3012,7 @@ os_prompt% </pre> <fsummary>Set the owner of a port</fsummary> <desc> <p>Sets the port owner (the connected port) to <c><anno>Pid</anno></c>. - Roughly the same as <c><anno>Port</anno> ! {self(), {connect, <anno>Pid</anno>}}</c> + Roughly the same as <c><anno>Port</anno> ! {Owner, {connect, <anno>Pid</anno>}}</c> except for the following:</p> <list type="bulleted"> <item> @@ -3003,6 +3023,9 @@ os_prompt% </pre> <c>{Port,connected}</c>.</p> </item> <item> + <p><c>port_connect/1</c> is synchronous, see below.</p> + </item> + <item> <p>The new port owner gets linked to the port.</p> </item> </list> @@ -3026,11 +3049,14 @@ os_prompt% </pre> <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> just as if it itself was the port owner, but the reply always goes to the port owner.</p> - <p>In short: <c>port_connect(<anno>Port</anno>, <anno>Pid</anno>)</c> has a cleaner and - more logical behaviour than - <c><anno>Port</anno> ! {self(),{connect,<anno>Pid</anno>}}</c>.</p> + <p>As of OTP-R16 <c><anno>Port</anno> ! {PortOwner, {connect, <anno>Pid</anno>}}</c> is + truly asynchronous. Note that this operation has always been + documented as an asynchronous operation, while the underlying + implementation has been synchronous. <c>port_connect/2</c> is + however still fully synchronous. This due to its error + behavior.</p> <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not an open port - or the registered name of an open port, or if <c><anno>Pid</anno></c> is + or the registered name of an open port, or if <c>Pid</c> is not an existing local pid.</p> </desc> </func> @@ -3077,71 +3103,187 @@ os_prompt% </pre> </func> <func> <name name="port_info" arity="1"/> - <type name="port_info_result_item"/> <fsummary>Information about a port</fsummary> <desc> <p>Returns a list containing tuples with information about the <c><anno>Port</anno></c>, or <c>undefined</c> if the port is not open. The order of the tuples is not defined, nor are all the tuples mandatory.</p> - <taglist> - <tag><c>{registered_name, <anno>RegName</anno>}</c></tag> - <item> - <p><c><anno>RegName</anno></c> (an atom) is the registered name of - the port. If the port has no registered name, this tuple - is not present in the list.</p> - </item> - <tag><c>{id, <anno>Index</anno>}</c></tag> - <item> - <p><c><anno>Index</anno></c> (an integer) is the internal index of the - port. This index may be used to separate ports.</p> - </item> - <tag><c>{connected, <anno>Pid</anno>}</c></tag> - <item> - <p><c><anno>Pid</anno></c> is the process connected to the port.</p> - </item> - <tag><c>{links, <anno>Pids</anno>}</c></tag> - <item> - <p><c><anno>Pids</anno></c> is a list of pids to which processes the - port is linked.</p> - </item> - <tag><c>{name, <anno>String</anno>}</c></tag> - <item> - <p><c><anno>String</anno></c> is the command name set by - <c>open_port</c>.</p> - </item> - <tag><c>{input, <anno>Bytes</anno>}</c></tag> - <item> - <p><c><anno>Bytes</anno></c> is the total number of bytes read from - the port.</p> - </item> - <tag><c>{output, <anno>Bytes</anno>}</c></tag> - <item> - <p><c><anno>Bytes</anno></c> is the total number of bytes written to - the port.</p> - </item> - <tag><c>{os_pid, <anno>OsPid</anno> | undefined}</c></tag> - <item> - <p><c> <anno>OsPid</anno></c> is the process identifier (or equivalent) of an OS process created with <c>open_port({spawn | spawn_executable, Command}, Options)</c>. If the port is not the result of spawning an OS process, the value is <c>undefined</c>.</p> - </item> - </taglist> - <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local port.</p> + <p>Currently the result will containt information about the + following <c>Item</c>s: <c>registered_name</c> (if the port has + a registered name), <c>id</c>, <c>connected</c>, <c>links</c>, + <c>name</c>, <c>input</c>, and <c>output</c>. For more information + about the different <c>Item</c>s, see + <seealso marker="#port_info/2">port_info/2</seealso>.</p> + <p>Failure: <c>badarg</c> if <c>Port</c> is not a local port + identifier, or an atom.</p> </desc> </func> <func> - <name name="port_info" arity="2"/> - <type name="port_info_item"/> - <type name="port_info_result_item"/> - <fsummary>Information about a port</fsummary> + <name name="port_info" arity="2" clause_i="1"/> + <fsummary>Information about the connected process of a port</fsummary> + <desc> + <p><c><anno>Pid</anno></c> is the process identifier of the process + connected to the port.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="2"/> + <fsummary>Information about the internal index of a port</fsummary> + <desc> + <p><c><anno>Index</anno></c> is the internal index of the port. This + index may be used to separate ports.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="3"/> + <fsummary>Information about the input of a port</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number of bytes + read from the port.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="4"/> + <fsummary>Information about the links of a port</fsummary> + <desc> + <p><c><anno>Pids</anno></c> is a list of the process identifiers + of the processes that the port is linked to.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="5"/> + <fsummary>Information about the locking of a port</fsummary> <desc> - <p>Returns information about <c><anno>Port</anno></c> as specified - by <c><anno>Item</anno></c>, or <c>undefined</c> if the port is not open. - Also, if <c>Item =:= registered_name</c> and the port has no - registered name, <c>[]</c> is returned.</p> - <p>For valid values of <c><anno>Item</anno></c>, and corresponding - values of <c><anno>Result</anno></c>, see - <seealso marker="#port_info/1">erlang:port_info/1</seealso>.</p> - <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local port.</p> + <p><c><anno>Locking</anno></c> is currently either <c>false</c> + (emulator without SMP support), <c>port_level</c> (port specific + locking), or <c>driver_level</c> (driver specific locking). Note + that these results are highly implementation specific and might + change in the future.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="6"/> + <fsummary>Information about the memory size of a port</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total amount of memory, + in bytes, allocated for this port by the runtime system. Note + that the port itself might have allocated memory which is not + included in <c><anno>Bytes</anno></c>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="7"/> + <fsummary>Information about the monitors of a port</fsummary> + <desc> + <p><c><anno>Monitors</anno></c> represent processes that this port + is monitoring.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="8"/> + <fsummary>Information about the name of a port</fsummary> + <desc> + <p><c><anno>Name</anno></c> is the command name set by + <seealso marker="#open_port/2">open_port/2</seealso>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="9"/> + <fsummary>Information about the OS pid of a port</fsummary> + <desc> + <p><c><anno>OsPid</anno></c> is the process identifier (or equivalent) + of an OS process created with + <seealso marker="#open_port/2">open_port({spawn | spawn_executable, + Command}, Options)</seealso>. If the port is not the result of spawning + an OS process, the value is <c>undefined</c>.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="10"/> + <fsummary>Information about the output of a port</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total number of bytes written + to the port from Erlang processes using either + <seealso marker="#port_command/2">port_command/2</seealso>, + <seealso marker="#port_command/3">port_command/3</seealso>, + or <c><anno>Port</anno> ! {Owner, {command, Data}</c>. + </p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="11"/> + <fsummary>Information about the parallelism hint of a port</fsummary> + <desc> + <p><c><anno>Boolean</anno></c> corresponds to the port parallelism + hint being used by this port. For more information see + the <seealso marker="#open_port_parallelism">parallelism</seealso> + option of <seealso marker="#open_port/2">open_port/2</seealso>.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="12"/> + <fsummary>Information about the queue size of a port</fsummary> + <desc> + <p><c><anno>Bytes</anno></c> is the total amount of data, + in bytes, queued by the port using the ERTS driver queue + implementation.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> + </desc> + </func> + <func> + <name name="port_info" arity="2" clause_i="13"/> + <fsummary>Information about the registered name of a port</fsummary> + <desc> + <p><c><anno>RegisteredName</anno></c> is the registered name of + the port. If the port has no registered name, <c>[]</c> is returned.</p> + <p>If the port identified by <c><anno>Port</anno></c> is not open, + <c>undefined</c> is returned.</p> + <p>Failure: <c>badarg</c> if <c><anno>Port</anno></c> is not a local + port identifier, or an atom.</p> </desc> </func> <func> @@ -3161,7 +3303,10 @@ os_prompt% </pre> <name name="ports" arity="0"/> <fsummary>All open ports</fsummary> <desc> - <p>Returns a list of all ports on the local node.</p> + <p>Returns a list of port identifiers corresponding to all the + ports currently existing on the local node.</p> + + <p>Note that a port that is exiting, exists but is not open.</p> </desc> </func> <func> @@ -5494,19 +5639,40 @@ ok <item> <p>Returns a string containing the OTP release number.</p> </item> + <tag><marker id="system_info_port_parallelism"><c>port_parallelism</c></marker></tag> + <item><p>Returns the default port parallelism scheduling hint used. + For more information see the + <seealso marker="erl#+spp">+spp</seealso> command line argument + of <seealso marker="erl">erl(1)</seealso>.</p></item> + <tag><c>process_count</c></tag> + <item> + <p>Returns the number of ports currently existing at + the local node as an integer. The same value as + <c>length(erlang:ports())</c> returns.</p> + </item> + <tag><marker id="system_info_port_limit"><c>port_limit</c></marker></tag> + <item> + <p>Returns the maximum number of simultaneously existing + ports at the local node as an integer. This limit + can be configured at startup by using the + <seealso marker="erl#max_ports"><c>+Q</c></seealso> + command line flag of + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> + </item> <tag><c>process_count</c></tag> <item> <p>Returns the number of processes currently existing at the local node as an integer. The same value as <c>length(processes())</c> returns.</p> </item> - <tag><c>process_limit</c></tag> + <tag><marker id="system_info_process_limit"><c>process_limit</c></marker></tag> <item> - <p>Returns the maximum number of concurrently existing + <p>Returns the maximum number of simultaneously existing processes at the local node as an integer. This limit - can be configured at startup by using the command line - flag <c>+P</c>, see - <seealso marker="erts:erl#max_processes">erl(1)</seealso>.</p> + can be configured at startup by using the + <seealso marker="erl#max_processes"><c>+P</c></seealso> + command line flag of + <seealso marker="erl"><c>erl(1)</c></seealso>.</p> </item> <tag><c>procs</c></tag> <item> diff --git a/erts/doc/src/part.xml b/erts/doc/src/part.xml index e27b722721..2c178556d4 100644 --- a/erts/doc/src/part.xml +++ b/erts/doc/src/part.xml @@ -31,6 +31,7 @@ <description> <p>The Erlang Runtime System Application <em>ERTS</em>.</p> </description> + <xi:include href="communication.xml"/> <xi:include href="match_spec.xml"/> <xi:include href="crash_dump.xml"/> <xi:include href="alt_dist.xml"/> |