aboutsummaryrefslogtreecommitdiffstats
path: root/erts/doc/src/erl_driver.xml
diff options
context:
space:
mode:
Diffstat (limited to 'erts/doc/src/erl_driver.xml')
-rw-r--r--erts/doc/src/erl_driver.xml185
1 files changed, 159 insertions, 26 deletions
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>