From 23c6f9e07a3cae7c05e55abd01ff798384241538 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Sun, 16 Sep 2012 02:45:32 +0200 Subject: Add erl_drv_[send|output]_term --- erts/doc/src/erl_driver.xml | 104 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 84 insertions(+), 20 deletions(-) (limited to 'erts/doc/src/erl_driver.xml') diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index 4fd74b783e..fcce962557 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -123,12 +123,20 @@ different threads. This, however, is not a problem for any function in this API, since the emulator has control over these threads.

- -

Functions not explicitly documented as thread-safe are - not thread-safe. Also note that some functions + +

Functions not explicitly documented as thread safe are + not thread safe. Also note that some functions are only thread safe when used in a runtime system with SMP support.

-
+

A function not explicitly documented as thread safe may at + some point in time have a thread safe implementation in the + runtime system. Such an implementation may however change to + a thread unsafe implementation at any time without + any notice at all. +

+

Only use functions explicitly documented as thread safe + from arbitrary threads.

+
@@ -1570,6 +1578,8 @@ typedef struct ErlIOVec {

This function returns the port owner process.

+

Note that this function is not thread-safe, not + even when the emulator with SMP support is used.

@@ -1597,22 +1607,32 @@ typedef struct ErlIOVec { call Called from erlang:port_call/3 +

Note that this function is not thread-safe, not + even when the emulator with SMP support is used.

- intdriver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n) + interl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n) Send term data from driver to port owner - +

This functions sends data in the special driver term - 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.

+ format to the port owner process. This is a fast way to + deliver term data from a driver. It also needs no binary + conversion, so the port owner process receives data as + normal Erlang terms. The + erl_drv_send_term() + functions can be used for sending to any arbitrary process + on the local node.

+

Note that the port parameter is not + an ordinary port handle, but a port handle converted using + driver_mk_port().

The term parameter points to an array of ErlDrvTermData, with n elements. This array 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.

+ term first has a term type, and then arguments. The + port parameter specifies the sending port.

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 @@ -1664,17 +1684,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])); ]]>

Where bin is a driver binary of length at least 50 - and port is a port handle. Note that the ERL_DRV_LIST + and drvport is a port handle. Note that the ERL_DRV_LIST comes after the elements of the list, likewise the ERL_DRV_TUPLE.

The term ERL_DRV_STRING_CONS is a way to construct @@ -1695,7 +1715,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])); ]]>

The ERL_DRV_EXT2TERM term type is used for passing a term encoded with the @@ -1725,7 +1745,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])); ]]>

If you want to pass a binary and don't already have the content of the binary in an ErlDrvBinary, you can benefit from using @@ -1741,6 +1761,22 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len ERL_DRV_EXT2TERM term types were introduced in the 5.6 version of erts.

+

This function is only thread-safe when the emulator with SMP + support is used.

+
+
+ + intdriver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n) + Send term data from driver to port owner + + +

driver_output_term() is deferred and will + be removed in the OTP-R17 release. Use + erl_drv_output_term() + instead.

+
+

The parameters term and n do the same thing + as in erl_drv_output_term().

Note that this function is not thread-safe, not even when the emulator with SMP support is used.

@@ -1754,6 +1790,8 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len string. 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.

+

Note that this function is not thread-safe, not + even when the emulator with SMP support is used.

@@ -1762,20 +1800,46 @@ ERL_DRV_EXT2TERM char *buf, ErlDrvUInt len

This function converts a port handle to the erlang term - format, usable in the driver_output_send function.

+ format, usable in the erl_drv_output_term(), and erl_drv_send_term() functions.

+

Note that this function is not thread-safe, not + even when the emulator with SMP support is used.

- intdriver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) + interl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) Send term data to other process than port owner process - +

This function is the only way for a driver to send data to other processes than the port owner process. The receiver parameter specifies the process to receive the data.

+

Note that the port parameter is not + an ordinary port handle, but a port handle converted using + driver_mk_port().

+

The parameters port, term and n do the same thing + as in erl_drv_output_term().

+

This function is only thread-safe when the emulator with SMP + support is used.

+
+
+ + intdriver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) + Send term data to other process than port owner process + + +

driver_send_term() is deferred and will + be removed in the OTP-R17 release. Use + erl_drv_send_term() + instead.

+

Also note that parameters of driver_send_term() + cannot be properly checked by the runtime system when + executed by arbitrary threads. This may cause the + driver_send_term() function not to fail when + it should.

+

The parameters term and n do the same thing - as in driver_output_term.

+ as in erl_drv_output_term().

This function is only thread-safe when the emulator with SMP support is used.

-- cgit v1.2.3 From 9e4895da833b7777e69efc173f5dc777aaea3201 Mon Sep 17 00:00:00 2001 From: Rickard Green Date: Thu, 29 Nov 2012 01:24:43 +0100 Subject: Add support for busy port message queue --- erts/doc/src/erl_driver.xml | 81 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 6 deletions(-) (limited to 'erts/doc/src/erl_driver.xml') diff --git a/erts/doc/src/erl_driver.xml b/erts/doc/src/erl_driver.xml index fcce962557..903b8dfe64 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -1499,17 +1499,82 @@ typedef struct ErlIOVec { error terms from the driver.

+ + voiderl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high) + Set and get limits for busy port message queue + + +

Sets and gets limits that will be used for controling the + busy state of the port message queue.

+

The port message queue will be set into a busy + state when the amount of command data queued on the + message queue reaches the high limit. The port + message queue will be set into a not busy state when the + amount of command data queued on the message queue falls + below the low limit. Command data is in this + context data passed to the port using either + Port ! {Owner, {command, Data}}, or + port_command/[2,3]. Note that these limits + only concerns command data that have not yet reached the + port. The busy port + feature can be used for data that has reached the port.

+ +

Valid limits are values in the range + [ERL_DRV_BUSY_MSGQ_LIM_MIN, ERL_DRV_BUSY_MSGQ_LIM_MAX]. + Limits will be automatically adjusted to be sane. That is, + the system will adjust values so that the low limit used is + lower or equal to the high limit used. By default the high + limit will be 8 kB and the low limit will be 4 kB.

+ +

By passing a pointer to an integer variable containing + the value ERL_DRV_BUSY_MSGQ_READ_ONLY, currently used + limit will be read and written back to the integer variable. + A new limit can be set by passing a pointer to an integer + variable containing a valid limit. The passed value will be + written to the internal limit. The internal limit will then + be adjusted. After this the adjusted limit will be written + back to the integer variable from which the new value was + read. Values are in bytes.

+ +

The busy message queue feature can be disabled either + by setting the ERL_DRV_FLAG_NO_BUSY_MSGQ + driver flag + in the driver_entry + used by the driver, or by calling this function with + ERL_DRV_BUSY_MSGQ_DISABLED as a limit (either low or + high). When this feature has been disabled it cannot be + enabled again. When reading the limits both of them + will be ERL_DRV_BUSY_MSGQ_DISABLED, if this + feature has been disabled.

+ +

Processes sending command data to the port will be suspended + if either the port is busy or if the port message queue is + busy. Suspended processes will be resumed when neither the + port is busy, nor the port message queue is busy.

+ +

For information about busy port functionality + see the documentation of the + set_busy_port() + function.

+
+
voidset_busy_port(ErlDrvPort port, int on) Signal or unsignal port as busy -

This function set and resets the busy status of the port. If - on is 1, the port is set to busy, if it's 0 the port - is set to not busy.

-

When the port is busy, sending to it with Port ! Data - or port_command/2, will block the port owner process, - until the port is signaled as not busy.

+

This function set and unset the busy state of the port. If + on is non-zero, the port is set to busy, if it's zero the port + is set to not busy. You typically want to combine + this feature with the busy + port message queue functionality.

+

Processes sending command data to the port will be suspended + if either the port is busy or if the port message queue + is busy. Suspended processes will be resumed when neither the + port is busy, nor the port message queue is busy. Command data + is in this context data passed to the port using either + Port ! {Owner, {command, Data}}, or + port_command/[2,3].

If the has been set in the @@ -1518,6 +1583,10 @@ typedef struct ErlIOVec { port_command(Port, Data, [force]) even though the driver has signaled that it is busy.

+

For information about busy port message queue functionality + see the documentation of the + erl_drv_busy_msgq_limits() + function.

-- cgit v1.2.3