From d281213a4a04a61910a6c451d8f5c86e61416bb2 Mon Sep 17 00:00:00 2001 From: Lukas Larsson Date: Mon, 11 Jul 2016 17:05:31 +0200 Subject: erts: Move all functions in docs to be in alphabetical order This commit only changes the order of functions and does some other rearrangements to that the diff with the next commit will be easier to follow. No content or XML tags are changed. --- erts/doc/src/erl_driver.xml | 3173 ++++++++++++++++++++++--------------------- 1 file changed, 1615 insertions(+), 1558 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 82215ead46..d8116d4650 100644 --- a/erts/doc/src/erl_driver.xml +++ b/erts/doc/src/erl_driver.xml @@ -893,358 +893,339 @@ typedef struct ErlIOVec { - voiddriver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size) - Get information about the Erlang runtime system + voidadd_driver_entry(ErlDrvEntry *de) + Add a driver entry - -

This function will write information about the Erlang runtime - system into the - ErlDrvSysInfo - structure referred to by the first argument. The second - argument should be the size of the - ErlDrvSysInfo - structure, i.e., sizeof(ErlDrvSysInfo).

-

See the documentation of the - ErlDrvSysInfo - structure for information about specific fields.

+ +

This function adds a driver entry to the list of drivers + known by Erlang. The init function of the de + parameter is called.

+ +

To use this function for adding drivers residing in + dynamically loaded code is dangerous. If the driver code + for the added driver resides in the same dynamically + loaded module (i.e. .so file) as a normal + dynamically loaded driver (loaded with the erl_ddll + interface), the caller should call driver_lock_driver before + adding driver entries.

+

Use of this function is generally deprecated.

+
+ - intdriver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len) - Send data from driver to port owner + void *driver_alloc(ErlDrvSizeT size) + Allocate memory - -

The driver_output function is used to send data from - the driver up to the emulator. The data will be received as - terms or binary data, depending on how the driver port was - opened.

-

The data is queued in the port owner process' message - queue. Note that this does not yield to the emulator. (Since - the driver and the emulator run in the same thread.)

-

The parameter buf points to the data to send, and - len is the number of bytes.

-

The return value for all output functions is 0. (Unless the - driver is used for distribution, in which case it can fail - and return -1. For normal use, the output function always - returns 0.)

+ +

This function allocates a memory block of the size specified + in size, and returns it. This only fails on out of + memory, in that case NULL is returned. (This is most + often a wrapper for malloc).

+

Memory allocated must be explicitly freed with a corresponding + call to driver_free (unless otherwise stated).

+

This function is thread-safe.

+ - intdriver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len) - Send data and binary data to port owner + ErlDrvBinary *driver_alloc_binary(ErlDrvSizeT size) + Allocate a driver binary - -

The driver_output2 function first sends hbuf - (length in hlen) data as a list, regardless of port - settings. Then buf is sent as a binary or list. - E.g. if hlen is 3 then the port owner process will - receive [H1, H2, H3 | T].

-

The point of sending data as a list header, is to facilitate - matching on the data received.

-

The return value is 0 for normal use.

+ +

This function allocates a driver binary with a memory block + of at least size bytes, and returns a pointer to it, + or NULL on failure (out of memory). When a driver binary has + been sent to the emulator, it must not be altered. Every + allocated binary should be freed by a corresponding call to + driver_free_binary (unless otherwise stated).

+

Note that a driver binary has an internal reference counter, + this means that calling driver_free_binary it may not + actually dispose of it. If it's sent to the emulator, it may + be referenced there.

+

The driver binary has a field, orig_bytes, which + marks the start of the data in the binary.

+

This function is thread-safe.

+ - intdriver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len) - Send data from a driver binary to port owner + longdriver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*)) + Perform an asynchronous call within a driver - -

This function sends data to port owner process from a - driver binary, it has a header buffer (hbuf - and hlen) just like driver_output2. The - hbuf parameter can be NULL.

-

The parameter offset is an offset into the binary and - len is the number of bytes to send.

-

Driver binaries are created with driver_alloc_binary.

-

The data in the header is sent as a list and the binary as - an Erlang binary in the tail of the list.

-

E.g. if hlen is 2, then the port owner process will - receive >]]]>.

-

The return value is 0 for normal use.

-

Note that, using the binary syntax in Erlang, the driver - application can match the header directly from the binary, - so the header can be put in the binary, and hlen can be set - to 0.

+ +

This function performs an asynchronous call. The function + async_invoke is invoked in a thread separate from the + emulator thread. This enables the driver to perform + time-consuming, blocking operations without blocking the + emulator.

+

The async thread pool size can be set with the + +A + command line argument of erl(1). + If no async thread pool is available, the call is made + synchronously in the thread calling driver_async(). The + current number of async threads in the async thread pool can be + retrieved via + driver_system_info().

+

If there is a thread pool available, a thread will be + used. If the key argument is null, the threads from the + pool are used in a round-robin way, each call to + driver_async uses the next thread in the pool. With the + key argument set, this behaviour is changed. The two + same values of *key always get the same thread.

+

To make sure that a driver instance always uses the same + thread, the following call can be used:

+

+ +

It is enough to initialize myKey once for each + driver instance.

+

If a thread is already working, the calls will be + queued up and executed in order. Using the same thread for + each driver instance ensures that the calls will be made in + sequence.

+

The async_data is the argument to the functions + async_invoke and async_free. It's typically a + pointer to a structure that contains a pipe or event that + can be used to signal that the async operation completed. + The data should be freed in async_free.

+

When the async operation is done, ready_async driver + entry function is called. If ready_async is null in + the driver entry, the async_free function is called + instead.

+

The return value is -1 if the driver_async call + fails.

+ +

As of erts version 5.5.4.3 the default stack size for + threads in the async-thread pool is 16 kilowords, + i.e., 64 kilobyte on 32-bit architectures. + This small default size has been chosen since the + amount of async-threads might be quite large. The + default stack size is enough for drivers delivered + with Erlang/OTP, but might not be sufficiently large + for other dynamically linked in drivers that use the + driver_async() functionality. A suggested stack size + for threads in the async-thread pool can be configured + via the + +a + command line argument of + erl(1).

+
- - intdriver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip) - Send vectorized data to port owner + + unsigned intdriver_async_port_key (ErlDrvPort port) + Calculate an async key from an ErlDrvPort - -

This function sends data from an IO vector, ev, to - the port owner process. It has a header buffer (hbuf - and hlen), just like driver_output2.

-

The skip parameter is a number of bytes to skip of - the ev vector from the head.

-

You get vectors of ErlIOVec type from the driver - queue (see below), and the outputv driver entry - function. You can also make them yourself, if you want to - send several ErlDrvBinary buffers at once. Often - it is faster to use driver_output or - driver_output_binary.

-

E.g. if hlen is 2 and ev points to an array of - three binaries, the port owner process will receive >, <> | <>]]]>.

-

The return value is 0 for normal use.

-

The comment for driver_output_binary applies for - driver_outputv too.

+ +

This function calculates a key for later use in driver_async(). The keys are + evenly distributed so that a fair mapping between port id's + and async thread id's is achieved.

+ +

Before OTP-R16, the actual port id could be used as a key + with proper casting, but after the rewrite of the port + subsystem, this is no longer the case. With this function, you + can achieve the same distribution based on port id's as before + OTP-R16.

+
+ - ErlDrvSizeTdriver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len) - Collect data segments into a buffer + longdriver_binary_dec_refc(ErlDrvBinary *bin) + Decrement the reference count of a driver binary - -

This function collects several segments of data, referenced - by ev, by copying them in order to the buffer - buf, of the size len.

-

If the data is to be sent from the driver to the port owner - process, it is faster to use driver_outputv.

-

The return value is the space left in the buffer, i.e. if - the ev contains less than len bytes it's the - difference, and if ev contains len bytes or - more, it's 0. This is faster if there is more than one header byte, - since the binary syntax can construct integers directly from - the binary.

+ +

Decrements the reference count on bin and returns + the reference count reached after the decrement.

+

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

+ +

You should normally decrement the reference count of a + driver binary by calling + driver_free_binary(). + driver_binary_dec_refc() does not free + the binary if the reference count reaches zero. Only + use driver_binary_dec_refc() when you are sure + not to reach a reference count of zero.

+
+ - intdriver_set_timer(ErlDrvPort port, unsigned long time) - Set a timer to call the driver + longdriver_binary_get_refc(ErlDrvBinary *bin) + Get the reference count of a driver binary - -

This function sets a timer on the driver, which will count - down and call the driver when it is timed out. The - time parameter is the time in milliseconds before the - timer expires.

-

When the timer reaches 0 and expires, the driver entry - function timeout is called.

-

Note that there is only one timer on each driver instance; - setting a new timer will replace an older one.

-

Return value is 0 (-1 only when the timeout driver - function is NULL).

+ +

Returns current reference count on bin.

+

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

+ - intdriver_cancel_timer(ErlDrvPort port) - Cancel a previously set timer - - -

This function cancels a timer set with - driver_set_timer.

-

The return value is 0.

-
-
- - intdriver_read_timer(ErlDrvPort port, unsigned long *time_left) - Read the time left before timeout + longdriver_binary_inc_refc(ErlDrvBinary *bin) + Increment the reference count of a driver binary - -

This function reads the current time of a timer, and places - the result in time_left. This is the time in - milliseconds, before the timeout will occur.

-

The return value is 0.

+ +

Increments the reference count on bin and returns + the reference count reached after the increment.

+

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

+ - intdriver_get_now(ErlDrvNowData *now) - Read a system timestamp + ErlDrvTermDatadriver_caller(ErlDrvPort port) + Return the process making the driver call - -

This function is deprecated! Do not use it! - Use erl_drv_monotonic_time() - (perhaps in combination with - erl_drv_time_offset()) - instead.

-

This function reads a timestamp into the memory pointed to by - the parameter now. See the description of ErlDrvNowData for - specification of its fields.

-

The return value is 0 unless the now pointer is not - valid, in which case it is < 0.

+ +

This function returns the process id of the process that + made the current call to the driver. The process id can be + used with driver_send_term to send back data to the + caller. driver_caller() only returns valid data + when currently executing in one of the following driver + callbacks:

+ + start + Called from open_port/2. + output + Called from erlang:send/2, and + erlang:port_command/2 + outputv + Called from erlang:send/2, and + erlang:port_command/2 + control + Called from erlang:port_control/3 + call + Called from erlang:port_call/3 + +

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

+ - intdriver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on) - Provide an event for having the emulator call the driver + intdriver_cancel_timer(ErlDrvPort port) + Cancel a previously set timer - -

This function is used by drivers to provide the emulator with - events to check for. This enables the emulator to call the driver - when something has happened asynchronously.

-

The event argument identifies an OS-specific event object. - On Unix systems, the functions select/poll are used. The - event object must be a socket or pipe (or other object that - select/poll can use). - On windows, the Win32 API function WaitForMultipleObjects - is used. This places other restrictions on the event object. - Refer to the Win32 SDK documentation.

-

The on parameter should be 1 for setting events - and 0 for clearing them.

-

The mode argument is a bitwise-or combination of - ERL_DRV_READ, ERL_DRV_WRITE and ERL_DRV_USE. - The first two specify whether to wait for read events and/or write - events. A fired read event will call - ready_input - while a fired write event will call - ready_output. -

- -

Some OS (Windows) do not differentiate between read and write events. - The call-back for a fired event then only depends on the value of mode.

-
-

ERL_DRV_USE specifies if we are using the event object or if we want to close it. - On an emulator with SMP support, it is not safe to clear all events - and then close the event object after driver_select has - returned. Another thread may still be using the event object - internally. To safely close an event object call - driver_select with ERL_DRV_USE and on==0. That - will clear all events and then call - stop_select - when it is safe to close the event object. - ERL_DRV_USE should be set together with the first event - for an event object. It is harmless to set ERL_DRV_USE - even though it already has been done. Clearing all events but keeping - ERL_DRV_USE set will indicate that we are using the event - object and probably will set events for it again.

- -

ERL_DRV_USE was added in OTP release R13. Old drivers will still work - as before. But it is recommended to update them to use ERL_DRV_USE and - stop_select to make sure that event objects are closed in a safe way.

-
-

The return value is 0 (failure, -1, only if the - ready_input/ready_output is - NULL).

+ +

This function cancels a timer set with + driver_set_timer.

+

The return value is 0.

+ - void *driver_alloc(ErlDrvSizeT size) - Allocate memory + intdriver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2) + Compare two monitors - -

This function allocates a memory block of the size specified - in size, and returns it. This only fails on out of - memory, in that case NULL is returned. (This is most - often a wrapper for malloc).

-

Memory allocated must be explicitly freed with a corresponding - call to driver_free (unless otherwise stated).

-

This function is thread-safe.

+ +

This function is used to compare two ErlDrvMonitors. It + can also be used to imply some artificial order on monitors, + for whatever reason.

+

The function returns 0 if monitor1 and + monitor2 are equal, < 0 if monitor1 is less + than monitor2 and > 0 if monitor1 is greater + than monitor2.

+ - void *driver_realloc(void *ptr, ErlDrvSizeT size) - Resize an allocated memory block + ErlDrvTermDatadriver_connected(ErlDrvPort port) + Return the port owner process - -

This function resizes a memory block, either in place, or by - allocating a new block, copying the data and freeing the old - block. A pointer is returned to the reallocated memory. On - failure (out of memory), NULL is returned. (This is - most often a wrapper for realloc.)

-

This function is thread-safe.

+ +

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.

+ - voiddriver_free(void *ptr) - Free an allocated memory block + ErlDrvPortdriver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data) + Create a new port (driver instance) - -

This function frees the memory pointed to by ptr. The - memory should have been allocated with - driver_alloc. All allocated memory should be - deallocated, just once. There is no garbage collection in - drivers.

-

This function is thread-safe.

+

This function creates a new port executing the same driver + code as the port creating the new port. + A short description of the arguments:

+ + port + The port handle of the port (driver instance) creating + the new port. + owner_pid + The process id of the Erlang process which will be + owner of the new port. This process will be linked + to the new port. You usually want to use + driver_caller(port) as owner_pid. + name + The port name of the new port. You usually want to + use the same port name as the driver name + (driver_name + field of the + driver_entry). + drv_data + The driver defined handle that will be passed in subsequent + calls to driver call-backs. Note, that the + driver start call-back + will not be called for this new driver instance. + The driver defined handle is normally created in the + driver start call-back + when a port is created via + erlang:open_port/2. + +

The caller of driver_create_port() is allowed to + manipulate the newly created port when driver_create_port() + has returned. When + port level locking + is used, the creating port is, however, only allowed to + manipulate the newly created port until the current driver + call-back that was called by the emulator returns.

+ +

When + port level locking + is used, the creating port is only allowed to manipulate + the newly created port until the current driver call-back + returns.

+
+ - ErlDrvBinary *driver_alloc_binary(ErlDrvSizeT size) - Allocate a driver binary + intdriver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor) + Stop monitoring a process from a driver - -

This function allocates a driver binary with a memory block - of at least size bytes, and returns a pointer to it, - or NULL on failure (out of memory). When a driver binary has - been sent to the emulator, it must not be altered. Every - allocated binary should be freed by a corresponding call to - driver_free_binary (unless otherwise stated).

-

Note that a driver binary has an internal reference counter, - this means that calling driver_free_binary it may not - actually dispose of it. If it's sent to the emulator, it may - be referenced there.

-

The driver binary has a field, orig_bytes, which - marks the start of the data in the binary.

-

This function is thread-safe.

+ +

This function cancels a monitor created earlier.

+

The function returns 0 if a monitor was removed and > 0 + if the monitor did no longer exist.

+ - ErlDrvBinary *driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) - Resize a driver binary + ErlDrvSizeTdriver_deq(ErlDrvPort port, ErlDrvSizeT size) + Dequeue data from the head of the driver queue - -

This function resizes a driver binary, while keeping the - data. The resized driver binary is returned. On failure (out - of memory), NULL is returned.

-

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

+ +

This function dequeues data by moving the head pointer + forward in the driver queue by size bytes. The data + in the queue will be deallocated.

+

The return value is the number of bytes remaining in the queue + or -1 on failure.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+ - voiddriver_free_binary(ErlDrvBinary *bin) - Free a driver binary - - -

This function frees a driver binary bin, allocated - previously with driver_alloc_binary. Since binaries - in Erlang are reference counted, the binary may still be - around.

-

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

-
-
- - longdriver_binary_get_refc(ErlDrvBinary *bin) - Get the reference count of a driver binary - - -

Returns current reference count on bin.

-

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

-
-
- - longdriver_binary_inc_refc(ErlDrvBinary *bin) - Increment the reference count of a driver binary - - -

Increments the reference count on bin and returns - the reference count reached after the increment.

-

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

-
-
- - longdriver_binary_dec_refc(ErlDrvBinary *bin) - Decrement the reference count of a driver binary - - -

Decrements the reference count on bin and returns - the reference count reached after the decrement.

-

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

- -

You should normally decrement the reference count of a - driver binary by calling - driver_free_binary(). - driver_binary_dec_refc() does not free - the binary if the reference count reaches zero. Only - use driver_binary_dec_refc() when you are sure - not to reach a reference count of zero.

-
-
-
- - intdriver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len) - Enqueue data in the driver queue + intdriver_enq(ErlDrvPort port, char* buf, ErlDrvSizeT len) + Enqueue data in the driver queue

This function enqueues data in the driver queue. The data in @@ -1266,50 +1247,7 @@ typedef struct ErlIOVec { thread during the call.

- - intdriver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len) - Push data at the head of the driver queue - - -

This function puts data at the head of the driver queue. The - data in buf is copied (len bytes) and placed - at the beginning of the queue.

-

The return value is 0.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-
-
- - ErlDrvSizeTdriver_deq(ErlDrvPort port, ErlDrvSizeT size) - Dequeue data from the head of the driver queue - - -

This function dequeues data by moving the head pointer - forward in the driver queue by size bytes. The data - in the queue will be deallocated.

-

The return value is the number of bytes remaining in the queue - or -1 on failure.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-
-
- - ErlDrvSizeTdriver_sizeq(ErlDrvPort port) - Return the size of the driver queue - - -

This function returns the number of bytes currently in the - driver queue.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-
-
+ intdriver_enq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) Enqueue binary in the driver queue @@ -1327,64 +1265,7 @@ typedef struct ErlIOVec {

The return value is 0.

- - intdriver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) - Push binary at the head of the driver queue - - -

This function puts data in the binary bin, at - offset with length len at the head of the - driver queue. It is most often faster than - driver_pushq, because the data doesn't have to be - copied.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-

The return value is 0.

-
-
- - ErlDrvSizeTdriver_peekqv(ErlDrvPort port, ErlIOVec *ev) - Get the driver queue as an IO vector - - -

- This function retrieves the driver queue into a supplied - ErlIOVec ev. It also returns the queue size. - This is one of two ways to get data out of the queue. -

-

- If ev is NULL all ones i.e. -1 type cast to - ErlDrvSizeT is returned. -

-

Nothing is removed from the queue by this function, that must be done - with driver_deq.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-
-
- - SysIOVec *driver_peekq(ErlDrvPort port, int *vlen) - Get the driver queue as a vector - - -

This function retrieves the driver queue as a pointer to an - array of SysIOVecs. It also returns the number of - elements in vlen. This is one of two ways to get data - out of the queue.

-

Nothing is removed from the queue by this function, that must be done - with driver_deq.

-

The returned array is suitable to use with the Unix system - call writev.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

-
-
+ intdriver_enqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip) Enqueue vector in the driver queue @@ -1401,91 +1282,143 @@ typedef struct ErlIOVec { thread during the call.

+ - intdriver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip) - Push vector at the head of the driver queue + intdriver_failure_atom(ErlDrvPort port, char *string) + intdriver_failure_posix(ErlDrvPort port, int error) + intdriver_failure(ErlDrvPort port, int error) + Fail with error - -

This function puts the data in ev, skipping the first - skip bytes of it, at the head of the driver queue. - It is faster than driver_pushq, because the data - doesn't have to be copied.

+ + + +

These functions signal to Erlang that the driver has + encountered an error and should be closed. The port is + closed and the tuple {'EXIT', error, Err}, is sent to + the port owner process, where error is an error atom + (driver_failure_atom and + driver_failure_posix), or an integer + (driver_failure).

+

The driver should fail only when in severe error situations, + when the driver cannot possibly keep open, for instance + buffer allocation gets out of memory. For normal errors + it is more appropriate to send error codes with + driver_output.

The return value is 0.

-

This function can be called from an arbitrary thread if a - port data lock - associated with the port is locked by the calling - thread during the call.

+ - ErlDrvPDLdriver_pdl_create(ErlDrvPort port) - Create a port data lock + intdriver_failure_eof(ErlDrvPort port) + Fail with EOF - -

This function creates a port data lock associated with - the port. NOTE: Once a port data lock has - been created, it has to be locked during all operations - on the driver queue of the port.

-

On success a newly created port data lock is returned. On - failure NULL is returned. driver_pdl_create() will - fail if port is invalid or if a port data lock already has - been associated with the port.

+ +

This function signals to erlang that the driver has + encountered an EOF and should be closed, unless the port was + opened with the eof option, in that case eof is sent + to the port. Otherwise, the port is closed and an + 'EXIT' message is sent to the port owner process.

+

The return value is 0.

+ - voiddriver_pdl_lock(ErlDrvPDL pdl) - Lock port data lock + voiddriver_free(void *ptr) + Free an allocated memory block - -

This function locks the port data lock passed as argument - (pdl).

+ +

This function frees the memory pointed to by ptr. The + memory should have been allocated with + driver_alloc. All allocated memory should be + deallocated, just once. There is no garbage collection in + drivers.

This function is thread-safe.

+ - voiddriver_pdl_unlock(ErlDrvPDL pdl) - Unlock port data lock + voiddriver_free_binary(ErlDrvBinary *bin) + Free a driver binary - -

This function unlocks the port data lock passed as argument - (pdl).

-

This function is thread-safe.

+ +

This function frees a driver binary bin, allocated + previously with driver_alloc_binary. Since binaries + in Erlang are reference counted, the binary may still be + around.

+

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

+ - longdriver_pdl_get_refc(ErlDrvPDL pdl) - + ErlDrvTermDatadriver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor) + Retrieve the process id from a monitor - -

This function returns the current reference count of - the port data lock passed as argument (pdl).

-

This function is thread-safe.

+ +

The function returns the process id associated with a living + monitor. It can be used in the process_exit call-back to + get the process identification for the exiting process.

+

The function returns driver_term_nil if the monitor + no longer exists.

+ - longdriver_pdl_inc_refc(ErlDrvPDL pdl) - + intdriver_get_now(ErlDrvNowData *now) + Read a system timestamp - -

This function increments the reference count of - the port data lock passed as argument (pdl).

-

The current reference count after the increment has - been performed is returned.

-

This function is thread-safe.

+ +

This function is deprecated! Do not use it! + Use erl_drv_monotonic_time() + (perhaps in combination with + erl_drv_time_offset()) + instead.

+

This function reads a timestamp into the memory pointed to by + the parameter now. See the description of ErlDrvNowData for + specification of its fields.

+

The return value is 0 unless the now pointer is not + valid, in which case it is < 0.

+ - longdriver_pdl_dec_refc(ErlDrvPDL pdl) - + intdriver_lock_driver(ErlDrvPort port) + Make sure the driver is never unloaded - -

This function decrements the reference count of - the port data lock passed as argument (pdl).

-

The current reference count after the decrement has - been performed is returned.

-

This function is thread-safe.

+ +

This function locks the driver used by the port port + in memory for the rest of the emulator process' + lifetime. After this call, the driver behaves as one of Erlang's + statically linked in drivers.

+
+
+ + + ErlDrvTermDatadriver_mk_atom(char* string) + Make an atom from a name + + +

This function returns an atom given a name + string. The atom is created and won't change, so the + return value may be saved and reused, which is faster than + looking up the atom several times.

+

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

+
+
+ + + ErlDrvTermDatadriver_mk_port(ErlDrvPort port) + Make a erlang term port from a port + + +

This function converts a port handle to the erlang term + format, usable in the erl_drv_output_term(), and erl_drv_send_term() functions.

+

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

+ intdriver_monitor_process(ErlDrvPort port, ErlDrvTermData process, ErlDrvMonitor *monitor) Monitor a process from a driver @@ -1503,500 +1436,371 @@ typedef struct ErlIOVec { provided and > 0 if the process is no longer alive.

+ - intdriver_demonitor_process(ErlDrvPort port, const ErlDrvMonitor *monitor) - Stop monitoring a process from a driver + intdriver_output(ErlDrvPort port, char *buf, ErlDrvSizeT len) + Send data from driver to port owner - -

This function cancels a monitor created earlier.

-

The function returns 0 if a monitor was removed and > 0 - if the monitor did no longer exist.

+ +

The driver_output function is used to send data from + the driver up to the emulator. The data will be received as + terms or binary data, depending on how the driver port was + opened.

+

The data is queued in the port owner process' message + queue. Note that this does not yield to the emulator. (Since + the driver and the emulator run in the same thread.)

+

The parameter buf points to the data to send, and + len is the number of bytes.

+

The return value for all output functions is 0. (Unless the + driver is used for distribution, in which case it can fail + and return -1. For normal use, the output function always + returns 0.)

+ - ErlDrvTermDatadriver_get_monitored_process(ErlDrvPort port, const ErlDrvMonitor *monitor) - Retrieve the process id from a monitor + intdriver_output_binary(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, ErlDrvBinary* bin, ErlDrvSizeT offset, ErlDrvSizeT len) + Send data from a driver binary to port owner - -

The function returns the process id associated with a living - monitor. It can be used in the process_exit call-back to - get the process identification for the exiting process.

-

The function returns driver_term_nil if the monitor - no longer exists.

+ +

This function sends data to port owner process from a + driver binary, it has a header buffer (hbuf + and hlen) just like driver_output2. The + hbuf parameter can be NULL.

+

The parameter offset is an offset into the binary and + len is the number of bytes to send.

+

Driver binaries are created with driver_alloc_binary.

+

The data in the header is sent as a list and the binary as + an Erlang binary in the tail of the list.

+

E.g. if hlen is 2, then the port owner process will + receive >]]]>.

+

The return value is 0 for normal use.

+

Note that, using the binary syntax in Erlang, the driver + application can match the header directly from the binary, + so the header can be put in the binary, and hlen can be set + to 0.

+ - intdriver_compare_monitors(const ErlDrvMonitor *monitor1, const ErlDrvMonitor *monitor2) - Compare two monitors + intdriver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n) + Send term data from driver to port owner - -

This function is used to compare two ErlDrvMonitors. It - can also be used to imply some artificial order on monitors, - for whatever reason.

-

The function returns 0 if monitor1 and - monitor2 are equal, < 0 if monitor1 is less - than monitor2 and > 0 if monitor1 is greater - than monitor2.

+ +

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

+
+

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

+

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

+ - voidadd_driver_entry(ErlDrvEntry *de) - Add a driver entry + intdriver_output2(ErlDrvPort port, char *hbuf, ErlDrvSizeT hlen, char *buf, ErlDrvSizeT len) + Send data and binary data to port owner - -

This function adds a driver entry to the list of drivers - known by Erlang. The init function of the de - parameter is called.

- -

To use this function for adding drivers residing in - dynamically loaded code is dangerous. If the driver code - for the added driver resides in the same dynamically - loaded module (i.e. .so file) as a normal - dynamically loaded driver (loaded with the erl_ddll - interface), the caller should call driver_lock_driver before - adding driver entries.

-

Use of this function is generally deprecated.

-
+ +

The driver_output2 function first sends hbuf + (length in hlen) data as a list, regardless of port + settings. Then buf is sent as a binary or list. + E.g. if hlen is 3 then the port owner process will + receive [H1, H2, H3 | T].

+

The point of sending data as a list header, is to facilitate + matching on the data received.

+

The return value is 0 for normal use.

+ - intremove_driver_entry(ErlDrvEntry *de) - Remove a driver entry + intdriver_outputv(ErlDrvPort port, char* hbuf, ErlDrvSizeT hlen, ErlIOVec *ev, ErlDrvSizeT skip) + Send vectorized data to port owner - -

This function removes a driver entry de previously - added with add_driver_entry.

-

Driver entries added by the erl_ddll erlang interface can - not be removed by using this interface.

+ +

This function sends data from an IO vector, ev, to + the port owner process. It has a header buffer (hbuf + and hlen), just like driver_output2.

+

The skip parameter is a number of bytes to skip of + the ev vector from the head.

+

You get vectors of ErlIOVec type from the driver + queue (see below), and the outputv driver entry + function. You can also make them yourself, if you want to + send several ErlDrvBinary buffers at once. Often + it is faster to use driver_output or + driver_output_binary.

+

E.g. if hlen is 2 and ev points to an array of + three binaries, the port owner process will receive >, <> | <>]]]>.

+

The return value is 0 for normal use.

+

The comment for driver_output_binary applies for + driver_outputv too.

+ - char *erl_errno_id(int error) - Get erlang error atom name from error number + ErlDrvPDLdriver_pdl_create(ErlDrvPort port) + Create a port data lock - -

This function returns the atom name of the erlang error, - given the error number in error. Error atoms are: - einval, enoent, etc. It can be used to make - error terms from the driver.

+ +

This function creates a port data lock associated with + the port. NOTE: Once a port data lock has + been created, it has to be locked during all operations + on the driver queue of the port.

+

On success a newly created port data lock is returned. On + failure NULL is returned. driver_pdl_create() will + fail if port is invalid or if a port data lock already has + been associated with the port.

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

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.

+ +

This function decrements the reference count of + the port data lock passed as argument (pdl).

+

The current reference count after the decrement has + been performed is returned.

+

This function is thread-safe.

+
+
-

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

+ + longdriver_pdl_get_refc(ErlDrvPDL pdl) + + + +

This function returns the current reference count of + the port data lock passed as argument (pdl).

+

This function is thread-safe.

+
+
-

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 unset the busy state of the port. If - on is non-zero, the port is set to busy, if it's zero the port - is set to not busy. You typically want to combine - this feature with the busy - port message queue functionality.

-

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

-

If the - - has been set in the - driver_entry, - data can be forced into the driver via - port_command(Port, Data, [force]) - even though the driver has signaled that it is busy. -

-

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

-
-
- - voidset_port_control_flags(ErlDrvPort port, int flags) - Set flags on how to handle control entry function + longdriver_pdl_inc_refc(ErlDrvPDL pdl) + - -

This function sets flags for how the control driver entry - function will return data to the port owner process. (The - control function is called from port_control/3 - in erlang.)

-

Currently there are only two meaningful values for - flags: 0 means that data is returned in a list, and - PORT_CONTROL_FLAG_BINARY means data is returned as - a binary from control.

+ +

This function increments the reference count of + the port data lock passed as argument (pdl).

+

The current reference count after the increment has + been performed is returned.

+

This function is thread-safe.

+ - intdriver_failure_eof(ErlDrvPort port) - Fail with EOF + voiddriver_pdl_lock(ErlDrvPDL pdl) + Lock port data lock - -

This function signals to erlang that the driver has - encountered an EOF and should be closed, unless the port was - opened with the eof option, in that case eof is sent - to the port. Otherwise, the port is closed and an - 'EXIT' message is sent to the port owner process.

-

The return value is 0.

+ +

This function locks the port data lock passed as argument + (pdl).

+

This function is thread-safe.

+ - intdriver_failure_atom(ErlDrvPort port, char *string) - intdriver_failure_posix(ErlDrvPort port, int error) - intdriver_failure(ErlDrvPort port, int error) - Fail with error + voiddriver_pdl_unlock(ErlDrvPDL pdl) + Unlock port data lock - - - -

These functions signal to Erlang that the driver has - encountered an error and should be closed. The port is - closed and the tuple {'EXIT', error, Err}, is sent to - the port owner process, where error is an error atom - (driver_failure_atom and - driver_failure_posix), or an integer - (driver_failure).

-

The driver should fail only when in severe error situations, - when the driver cannot possibly keep open, for instance - buffer allocation gets out of memory. For normal errors - it is more appropriate to send error codes with - driver_output.

-

The return value is 0.

+ +

This function unlocks the port data lock passed as argument + (pdl).

+

This function is thread-safe.

+ - ErlDrvTermDatadriver_connected(ErlDrvPort port) - Return the port owner process + SysIOVec *driver_peekq(ErlDrvPort port, int *vlen) + Get the driver queue as a vector - -

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.

+ +

This function retrieves the driver queue as a pointer to an + array of SysIOVecs. It also returns the number of + elements in vlen. This is one of two ways to get data + out of the queue.

+

Nothing is removed from the queue by this function, that must be done + with driver_deq.

+

The returned array is suitable to use with the Unix system + call writev.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+ - ErlDrvTermDatadriver_caller(ErlDrvPort port) - Return the process making the driver call + ErlDrvSizeTdriver_peekqv(ErlDrvPort port, ErlIOVec *ev) + Get the driver queue as an IO vector - -

This function returns the process id of the process that - made the current call to the driver. The process id can be - used with driver_send_term to send back data to the - caller. driver_caller() only returns valid data - when currently executing in one of the following driver - callbacks:

- - start - Called from open_port/2. - output - Called from erlang:send/2, and - erlang:port_command/2 - outputv - Called from erlang:send/2, and - erlang:port_command/2 - control - Called from erlang:port_control/3 - call - Called from erlang:port_call/3 - -

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

+ +

+ This function retrieves the driver queue into a supplied + ErlIOVec ev. It also returns the queue size. + This is one of two ways to get data out of the queue. +

+

+ If ev is NULL all ones i.e. -1 type cast to + ErlDrvSizeT is returned. +

+

Nothing is removed from the queue by this function, that must be done + with driver_deq.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+ - interl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n) - Send term data from driver to port owner + intdriver_pushq(ErlDrvPort port, char* buf, ErlDrvSizeT len) + Push data at the head of the driver queue - -

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

-

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

-

The term parameter points to an array of - ErlDrvTermData, with n elements. This array - contains terms described in the driver term format. Every - term consists of one to four elements in the array. The - term first has a term type, and then arguments. The - port parameter specifies the sending port.

-

Tuples, maps and lists (with the exception of strings, see below), - are built in reverse polish notation, so that to build a - tuple, the elements are given first, and then the tuple - term, with a count. Likewise for lists and maps.

-

A tuple must be specified with the number of elements. (The - elements precede the ERL_DRV_TUPLE term.)

-

A list must be specified with the number of elements, - including the tail, which is the last term preceding - ERL_DRV_LIST.

-

A map must be specified with the number of key-value pairs N. - The key-value pairs must precede the ERL_DRV_MAP in this order: - key1,value1,key2,value2,...,keyN,valueN. - Duplicate keys are not allowed.

-

The special term ERL_DRV_STRING_CONS is used to - "splice" in a string in a list, a string given this way is - not a list per se, but the elements are elements of the - surrounding list.

-
-Term type            Argument(s)
-===========================================
-ERL_DRV_NIL
-ERL_DRV_ATOM         ErlDrvTermData atom (from driver_mk_atom(char *string))
-ERL_DRV_INT          ErlDrvSInt integer
-ERL_DRV_UINT         ErlDrvUInt integer
-ERL_DRV_INT64        ErlDrvSInt64 *integer_ptr
-ERL_DRV_UINT64       ErlDrvUInt64 *integer_ptr
-ERL_DRV_PORT         ErlDrvTermData port (from driver_mk_port(ErlDrvPort port))
-ERL_DRV_BINARY       ErlDrvBinary *bin, ErlDrvUInt len, ErlDrvUInt offset
-ERL_DRV_BUF2BINARY   char *buf, ErlDrvUInt len
-ERL_DRV_STRING       char *str, int len
-ERL_DRV_TUPLE        int sz
-ERL_DRV_LIST         int sz
-ERL_DRV_PID          ErlDrvTermData pid (from driver_connected(ErlDrvPort port) or driver_caller(ErlDrvPort port))
-ERL_DRV_STRING_CONS  char *str, int len
-ERL_DRV_FLOAT        double *dbl
-ERL_DRV_EXT2TERM     char *buf, ErlDrvUInt len
-ERL_DRV_MAP          int sz
-        
-

The unsigned integer data type ErlDrvUInt and the - signed integer data type ErlDrvSInt are 64 bits wide - on a 64 bit runtime system and 32 bits wide on a 32 bit - runtime system. They were introduced in erts version 5.6, - and replaced some of the int arguments in the list above. -

-

The unsigned integer data type ErlDrvUInt64 and the - signed integer data type ErlDrvSInt64 are always 64 bits - wide. They were introduced in erts version 5.7.4. -

- -

To build the tuple {tcp, Port, [100 | Binary]}, the - following call could be made.

- - -

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

-

The term ERL_DRV_STRING_CONS is a way to construct - strings. It works differently from how ERL_DRV_STRING - works. ERL_DRV_STRING_CONS builds a string list in - reverse order, (as opposed to how ERL_DRV_LIST - works), concatenating the strings added to a list. The tail - must be given before ERL_DRV_STRING_CONS.

-

The ERL_DRV_STRING constructs a string, and ends - it. (So it's the same as ERL_DRV_NIL followed by - ERL_DRV_STRING_CONS.)

- -

- -

The ERL_DRV_EXT2TERM term type is used for passing a - term encoded with the - external format, - i.e., a term that has been encoded by - erlang:term_to_binary, - erl_interface, etc. - For example, if binp is a pointer to an ErlDrvBinary - that contains the term {17, 4711} encoded with the - external format - and you want to wrap it in a two tuple with the tag my_tag, - i.e., {my_tag, {17, 4711}}, you can do as follows: -

- orig_bytes, binp->orig_size - ERL_DRV_TUPLE, 2, - }; - erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); - ]]> - -

To build the map #{key1 => 100, key2 => {200, 300}}, the - following call could be made.

- - + +

This function puts data at the head of the driver queue. The + data in buf is copied (len bytes) and placed + at the beginning of the queue.

+

The return value is 0.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+
+
-

If you want to pass a binary and don't already have the content - of the binary in an ErlDrvBinary, you can benefit from using - ERL_DRV_BUF2BINARY instead of creating an ErlDrvBinary - via driver_alloc_binary() and then pass the binary via - ERL_DRV_BINARY. The runtime system will often allocate - binaries smarter if ERL_DRV_BUF2BINARY is used. - However, if the content of the binary to pass already resides in - an ErlDrvBinary, it is normally better to pass the binary - using ERL_DRV_BINARY and the ErlDrvBinary in question. -

-

The ERL_DRV_UINT, ERL_DRV_BUF2BINARY, and - ERL_DRV_EXT2TERM term types were introduced in the 5.6 - version of erts. -

-

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

+ + intdriver_pushq_bin(ErlDrvPort port, ErlDrvBinary *bin, ErlDrvSizeT offset, ErlDrvSizeT len) + Push binary at the head of the driver queue + + +

This function puts data in the binary bin, at + offset with length len at the head of the + driver queue. It is most often faster than + driver_pushq, because the data doesn't have to be + copied.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+

The return value is 0.

+ - intdriver_output_term(ErlDrvPort port, ErlDrvTermData* term, int n) - Send term data from driver to port owner + intdriver_pushqv(ErlDrvPort port, ErlIOVec *ev, ErlDrvSizeT skip) + Push vector at the head of the driver queue - -

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

-
-

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

-

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

+ +

This function puts the data in ev, skipping the first + skip bytes of it, at the head of the driver queue. + It is faster than driver_pushq, because the data + doesn't have to be copied.

+

The return value is 0.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+ - ErlDrvTermDatadriver_mk_atom(char* string) - Make an atom from a name + intdriver_read_timer(ErlDrvPort port, unsigned long *time_left) + Read the time left before timeout - -

This function returns an atom given a name - string. The atom is created and won't change, so the - return value may be saved and reused, which is faster than - looking up the atom several times.

-

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

+ +

This function reads the current time of a timer, and places + the result in time_left. This is the time in + milliseconds, before the timeout will occur.

+

The return value is 0.

+ - ErlDrvTermDatadriver_mk_port(ErlDrvPort port) - Make a erlang term port from a port + void *driver_realloc(void *ptr, ErlDrvSizeT size) + Resize an allocated memory block - -

This function converts a port handle to the erlang term - format, usable in the erl_drv_output_term(), and erl_drv_send_term() functions.

-

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

+ +

This function resizes a memory block, either in place, or by + allocating a new block, copying the data and freeing the old + block. A pointer is returned to the reallocated memory. On + failure (out of memory), NULL is returned. (This is + most often a wrapper for realloc.)

+

This function is thread-safe.

+ - interl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) - Send term data to other process than port owner process + ErlDrvBinary *driver_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) + Resize a driver binary - -

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 resizes a driver binary, while keeping the + data. The resized driver binary is returned. On failure (out + of memory), NULL is returned.

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

+ + + intdriver_select(ErlDrvPort port, ErlDrvEvent event, int mode, int on) + Provide an event for having the emulator call the driver + + +

This function is used by drivers to provide the emulator with + events to check for. This enables the emulator to call the driver + when something has happened asynchronously.

+

The event argument identifies an OS-specific event object. + On Unix systems, the functions select/poll are used. The + event object must be a socket or pipe (or other object that + select/poll can use). + On windows, the Win32 API function WaitForMultipleObjects + is used. This places other restrictions on the event object. + Refer to the Win32 SDK documentation.

+

The on parameter should be 1 for setting events + and 0 for clearing them.

+

The mode argument is a bitwise-or combination of + ERL_DRV_READ, ERL_DRV_WRITE and ERL_DRV_USE. + The first two specify whether to wait for read events and/or write + events. A fired read event will call + ready_input + while a fired write event will call + ready_output. +

+ +

Some OS (Windows) do not differentiate between read and write events. + The call-back for a fired event then only depends on the value of mode.

+
+

ERL_DRV_USE specifies if we are using the event object or if we want to close it. + On an emulator with SMP support, it is not safe to clear all events + and then close the event object after driver_select has + returned. Another thread may still be using the event object + internally. To safely close an event object call + driver_select with ERL_DRV_USE and on==0. That + will clear all events and then call + stop_select + when it is safe to close the event object. + ERL_DRV_USE should be set together with the first event + for an event object. It is harmless to set ERL_DRV_USE + even though it already has been done. Clearing all events but keeping + ERL_DRV_USE set will indicate that we are using the event + object and probably will set events for it again.

+ +

ERL_DRV_USE was added in OTP release R13. Old drivers will still work + as before. But it is recommended to update them to use ERL_DRV_USE and + stop_select to make sure that event objects are closed in a safe way.

+
+

The return value is 0 (failure, -1, only if the + ready_input/ready_output is + NULL).

+
+
+ intdriver_send_term(ErlDrvPort port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) Send term data to other process than port owner process @@ -2018,368 +1822,338 @@ ERL_DRV_MAP int sz support is used.

- - longdriver_async (ErlDrvPort port, unsigned int* key, void (*async_invoke)(void*), void* async_data, void (*async_free)(void*)) - Perform an asynchronous call within a driver - - -

This function performs an asynchronous call. The function - async_invoke is invoked in a thread separate from the - emulator thread. This enables the driver to perform - time-consuming, blocking operations without blocking the - emulator.

-

The async thread pool size can be set with the - +A - command line argument of erl(1). - If no async thread pool is available, the call is made - synchronously in the thread calling driver_async(). The - current number of async threads in the async thread pool can be - retrieved via - driver_system_info().

-

If there is a thread pool available, a thread will be - used. If the key argument is null, the threads from the - pool are used in a round-robin way, each call to - driver_async uses the next thread in the pool. With the - key argument set, this behaviour is changed. The two - same values of *key always get the same thread.

-

To make sure that a driver instance always uses the same - thread, the following call can be used:

-

- -

It is enough to initialize myKey once for each - driver instance.

-

If a thread is already working, the calls will be - queued up and executed in order. Using the same thread for - each driver instance ensures that the calls will be made in - sequence.

-

The async_data is the argument to the functions - async_invoke and async_free. It's typically a - pointer to a structure that contains a pipe or event that - can be used to signal that the async operation completed. - The data should be freed in async_free.

-

When the async operation is done, ready_async driver - entry function is called. If ready_async is null in - the driver entry, the async_free function is called - instead.

-

The return value is -1 if the driver_async call - fails.

- -

As of erts version 5.5.4.3 the default stack size for - threads in the async-thread pool is 16 kilowords, - i.e., 64 kilobyte on 32-bit architectures. - This small default size has been chosen since the - amount of async-threads might be quite large. The - default stack size is enough for drivers delivered - with Erlang/OTP, but might not be sufficiently large - for other dynamically linked in drivers that use the - driver_async() functionality. A suggested stack size - for threads in the async-thread pool can be configured - via the - +a - command line argument of - erl(1).

-
-
-
- unsigned intdriver_async_port_key (ErlDrvPort port) - Calculate an async key from an ErlDrvPort + intdriver_set_timer(ErlDrvPort port, unsigned long time) + Set a timer to call the driver - -

This function calculates a key for later use in driver_async(). The keys are - evenly distributed so that a fair mapping between port id's - and async thread id's is achieved.

- -

Before OTP-R16, the actual port id could be used as a key - with proper casting, but after the rewrite of the port - subsystem, this is no longer the case. With this function, you - can achieve the same distribution based on port id's as before - OTP-R16.

-
+ +

This function sets a timer on the driver, which will count + down and call the driver when it is timed out. The + time parameter is the time in milliseconds before the + timer expires.

+

When the timer reaches 0 and expires, the driver entry + function timeout is called.

+

Note that there is only one timer on each driver instance; + setting a new timer will replace an older one.

+

Return value is 0 (-1 only when the timeout driver + function is NULL).

+ - intdriver_lock_driver(ErlDrvPort port) - Make sure the driver is never unloaded + ErlDrvSizeTdriver_sizeq(ErlDrvPort port) + Return the size of the driver queue - -

This function locks the driver used by the port port - in memory for the rest of the emulator process' - lifetime. After this call, the driver behaves as one of Erlang's - statically linked in drivers.

+ +

This function returns the number of bytes currently in the + driver queue.

+

This function can be called from an arbitrary thread if a + port data lock + associated with the port is locked by the calling + thread during the call.

+ - ErlDrvPortdriver_create_port(ErlDrvPort port, ErlDrvTermData owner_pid, char* name, ErlDrvData drv_data) - Create a new port (driver instance) + voiddriver_system_info(ErlDrvSysInfo *sys_info_ptr, size_t size) + Get information about the Erlang runtime system -

This function creates a new port executing the same driver - code as the port creating the new port. - A short description of the arguments:

- - port - The port handle of the port (driver instance) creating - the new port. - owner_pid - The process id of the Erlang process which will be - owner of the new port. This process will be linked - to the new port. You usually want to use - driver_caller(port) as owner_pid. - name - The port name of the new port. You usually want to - use the same port name as the driver name - (driver_name - field of the - driver_entry). - drv_data - The driver defined handle that will be passed in subsequent - calls to driver call-backs. Note, that the - driver start call-back - will not be called for this new driver instance. - The driver defined handle is normally created in the - driver start call-back - when a port is created via - erlang:open_port/2. - -

The caller of driver_create_port() is allowed to - manipulate the newly created port when driver_create_port() - has returned. When - port level locking - is used, the creating port is, however, only allowed to - manipulate the newly created port until the current driver - call-back that was called by the emulator returns.

- -

When - port level locking - is used, the creating port is only allowed to manipulate - the newly created port until the current driver call-back - returns.

-
+ +

This function will write information about the Erlang runtime + system into the + ErlDrvSysInfo + structure referred to by the first argument. The second + argument should be the size of the + ErlDrvSysInfo + structure, i.e., sizeof(ErlDrvSysInfo).

+

See the documentation of the + ErlDrvSysInfo + structure for information about specific fields.

- - - voiderl_drv_init_ack(ErlDrvPort port, ErlDrvData res) - Acknowledge the start of the port + + ErlDrvSizeTdriver_vec_to_buf(ErlIOVec *ev, char *buf, ErlDrvSizeT len) + Collect data segments into a buffer - -

Arguments:

- - port - The port handle of the port (driver instance) creating - doing the acknowledgment. - - res - The result of the port initialization. This can be the same values - as the return value of start, - i.e any of the error codes or the ErlDrvData that is to be used for this - port. - - -

- When this function is called the initiating erlang:open_port call is - returned as if the start - function had just been called. It can only be used when the - ERL_DRV_FLAG_USE_INIT_ACK - flag has been set on the linked-in driver. -

+ +

This function collects several segments of data, referenced + by ev, by copying them in order to the buffer + buf, of the size len.

+

If the data is to be sent from the driver to the port owner + process, it is faster to use driver_outputv.

+

The return value is the space left in the buffer, i.e. if + the ev contains less than len bytes it's the + difference, and if ev contains len bytes or + more, it's 0. This is faster if there is more than one header byte, + since the binary syntax can construct integers directly from + the binary.

- voiderl_drv_set_os_pid(ErlDrvPort port, ErlDrvSInt pid) - Set the os_pid for the port + voiderl_drv_busy_msgq_limits(ErlDrvPort port, ErlDrvSizeT *low, ErlDrvSizeT *high) + Set and get limits for busy port message queue - -

Arguments:

- - port - The port handle of the port (driver instance) to set the pid on. - - pid - The pid to set. - -

- Set the os_pid seen when doing erlang:port_info/2 on this port. -

+ +

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

+

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

+ +

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

+ +

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

+ +

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

+ +

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

+ +

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

- interl_drv_thread_create(char *name, - ErlDrvTid *tid, - void * (*func)(void *), - void *arg, - ErlDrvThreadOpts *opts) - Create a thread + voiderl_drv_cond_broadcast(ErlDrvCond *cnd) + Broadcast on a condition variable - +

Arguments:

- name - A string identifying the created thread. It will be used - to identify the thread in planned future debug - functionality. - - tid - A pointer to a thread identifier variable. - func - A pointer to a function to execute in the created thread. - arg - A pointer to argument to the func function. - opts - A pointer to thread options to use or NULL. + cnd + A pointer to a condition variable to broadcast on. -

This function creates a new thread. On success 0 is returned; - otherwise, an errno value is returned to indicate the error. - The newly created thread will begin executing in the function pointed - to by func, and func will be passed arg as - argument. When erl_drv_thread_create() returns the thread - identifier of the newly created thread will be available in - *tid. opts can be either a NULL pointer, or a - pointer to an - ErlDrvThreadOpts - structure. If opts is a NULL pointer, default options - will be used; otherwise, the passed options will be used. -

-

You are not allowed to allocate the - ErlDrvThreadOpts - structure by yourself. It has to be allocated and - initialized by - erl_drv_thread_opts_create(). -

-

The created thread will terminate either when func returns - or if - erl_drv_thread_exit() - is called by the thread. The exit value of the thread is either - returned from func or passed as argument to - erl_drv_thread_exit(). - The driver creating the thread has the responsibility of joining the - thread, via - erl_drv_thread_join(), - before the driver is unloaded. It is not possible to create - "detached" threads, i.e., threads that don't need to be joined. +

This function broadcasts on a condition variable. That is, if + other threads are waiting on the condition variable being + broadcast on, all of them will be woken.

-

All created threads need to be joined by the driver before - it is unloaded. If the driver fails to join all threads - created before it is unloaded, the runtime system will - most likely crash when the code of the driver is unloaded. -

This function is thread-safe.

- ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name) - Create thread options + ErlDrvCond *erl_drv_cond_create(char *name) + Create a condition variable - +

Arguments:

name - A string identifying the created thread options. It will be used - to identify the thread options in planned future debug - functionality. + A string identifying the created condition variable. It + will be used to identify the condition variable in planned + future debug functionality. -

This function allocates and initialize a thread option - structure. On failure NULL is returned. A thread option - structure is used for passing options to - erl_drv_thread_create(). - If the structure isn't modified before it is passed to - erl_drv_thread_create(), - the default values will be used. -

-

You are not allowed to allocate the - ErlDrvThreadOpts - structure by yourself. It has to be allocated and - initialized by erl_drv_thread_opts_create(). -

+

This function creates a condition variable and returns a + pointer to it. On failure NULL is returned. The driver + creating the condition variable has the responsibility of + destroying it before the driver is unloaded.

This function is thread-safe.

- voiderl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts) - Destroy thread options + voiderl_drv_cond_destroy(ErlDrvCond *cnd) + Destroy a condition variable - +

Arguments:

- opts - A pointer to thread options to destroy. + cnd + A pointer to a condition variable to destroy. -

This function destroys thread options previously created by - erl_drv_thread_opts_create(). +

This function destroys a condition variable previously + created by + erl_drv_cond_create().

-

This function is thread-safe.

+

This function is thread-safe.

+ + char *erl_drv_cond_name(ErlDrvCond *cnd) + Get name of driver mutex. + + +

Arguments:

+ + cnd + A pointer to an initialized condition. + +

+ Returns a pointer to the name of the condition. +

+ +

This function is intended for debugging purposes only.

+
+
+
- voiderl_drv_thread_exit(void *exit_value) - Terminate calling thread + voiderl_drv_cond_signal(ErlDrvCond *cnd) + Signal on a condition variable - +

Arguments:

- exit_value - A pointer to an exit value or NULL. + cnd + A pointer to a condition variable to signal on. -

This function terminates the calling thread with the exit - value passed as argument. You are only allowed to terminate - threads created with - erl_drv_thread_create(). - The exit value can later be retrieved by another thread via - erl_drv_thread_join(). +

This function signals on a condition variable. That is, if + other threads are waiting on the condition variable being + signaled, one of them will be woken.

This function is thread-safe.

- interl_drv_thread_join(ErlDrvTid tid, void **exit_value) - Join with another thread + voiderl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx) + Wait on a condition variable - +

Arguments:

- tid - The thread identifier of the thread to join. - exit_value - A pointer to a pointer to an exit value, or NULL. + cnd + A pointer to a condition variable to wait on. + mtx + A pointer to a mutex to unlock while waiting. + + -

This function joins the calling thread with another thread, i.e., - the calling thread is blocked until the thread identified by - tid has terminated. On success 0 is returned; - otherwise, an errno value is returned to indicate the error. - A thread can only be joined once. The behavior of joining - more than once is undefined, an emulator crash is likely. If - exit_value == NULL, the exit value of the terminated thread - will be ignored; otherwise, the exit value of the terminated thread - will be stored at *exit_value. +

This function waits on a condition variable. The calling + thread is blocked until another thread wakes it by signaling + or broadcasting on the condition variable. Before the calling + thread is blocked it unlocks the mutex passed as argument, and + when the calling thread is woken it locks the same mutex before + returning. That is, the mutex currently has to be locked by + the calling thread when calling this function.

+

erl_drv_cond_wait() might return even though + no-one has signaled or broadcast on the condition + variable. Code calling erl_drv_cond_wait() should + always be prepared for erl_drv_cond_wait() + returning even though the condition that the thread was + waiting for hasn't occurred. That is, when returning from + erl_drv_cond_wait() always check if the condition + has occurred, and if not call erl_drv_cond_wait() + again. +

This function is thread-safe.

- ErlDrvTiderl_drv_thread_self(void) - Get the thread identifier of the current thread + interl_drv_consume_timeslice(ErlDrvPort port, int percent) + Give the runtime system a hint about how much CPU time the + current driver callback call has consumed - -

This function returns the thread identifier of the - calling thread. -

-

This function is thread-safe.

+ +

Arguments:

+ + port + Port handle of the executing port. + percent + Approximate consumed fraction of a full + time-slice in percent. + +

Give the runtime system a hint about how much CPU time the + current driver callback call has consumed since last hint, or + since the start of the callback if no previous hint has been given. + The time is given as a fraction, in percent, of a full time-slice + that a port is allowed to execute before it should surrender the + CPU to other runnable ports or processes. Valid range is + [1, 100]. The scheduling time-slice is not an exact entity, + but can usually be approximated to about 1 millisecond.

+ +

Note that it is up to the runtime system to determine if and + how to use this information. Implementations on some platforms + may use other means in order to determine the consumed fraction + of the time-slice. Lengthy driver callbacks should regardless of + this frequently call the erl_drv_consume_timeslice() + function in order to determine if it is allowed to continue + execution or not.

+ +

erl_drv_consume_timeslice() returns a non-zero value + if the time-slice has been exhausted, and zero if the callback is + allowed to continue execution. If a non-zero value is + returned the driver callback should return as soon as possible in + order for the port to be able to yield.

+ +

This function is provided to better support co-operative scheduling, + improve system responsiveness, and to make it easier to prevent + misbehaviors of the VM due to a port monopolizing a scheduler thread. + It can be used when dividing length work into a number of repeated + driver callback calls without the need to use threads. Also see the + important warning text at the + beginning of this document.

+ + ErlDrvTimeerl_drv_convert_time_unit(ErlDrvTime val, ErlDrvTimeUnit from, ErlDrvTimeUnit to) + Convert time unit of a time value + + +

Arguments:

+ + val + Value to convert time unit for. + from + Time unit of val. + to + Time unit of returned value. + +

Converts the val value of time unit from to + the corresponding value of time unit to. The result is + rounded using the floor function.

+

Returns ERL_DRV_TIME_ERROR if called with an invalid + time unit argument.

+

See also:

+ + ErlDrvTime + ErlDrvTimeUnit + +
+
+ interl_drv_equal_tids(ErlDrvTid tid1, ErlDrvTid tid2) Compare thread identifiers for equality @@ -2406,6 +2180,97 @@ ERL_DRV_MAP int sz + + interl_drv_getenv(const char *key, char *value, size_t *value_size) + Get the value of an environment variable + + +

Arguments:

+ + key + A null terminated string containing the + name of the environment variable. + value + A pointer to an output buffer. + value_size + A pointer to an integer. The integer is both used for + passing input and output sizes (see below). + + +

This function retrieves the value of an environment variable. + When called, *value_size should contain the size of + the value buffer. On success 0 is returned, + the value of the environment variable has been written to + the value buffer, and *value_size contains the + string length (excluding the terminating null character) of + the value written to the value buffer. On failure, + i.e., no such environment variable was found, a value less than + 0 is returned. When the size of the value + buffer is too small, a value greater than 0 is returned + and *value_size has been set to the buffer size needed. +

+

Do not use libc's getenv or similar + C library interfaces from a driver. +

+

This function is thread-safe.

+
+
+ + + voiderl_drv_init_ack(ErlDrvPort port, ErlDrvData res) + Acknowledge the start of the port + + +

Arguments:

+ + port + The port handle of the port (driver instance) creating + doing the acknowledgment. + + res + The result of the port initialization. This can be the same values + as the return value of start, + i.e any of the error codes or the ErlDrvData that is to be used for this + port. + + +

+ When this function is called the initiating erlang:open_port call is + returned as if the start + function had just been called. It can only be used when the + ERL_DRV_FLAG_USE_INIT_ACK + flag has been set on the linked-in driver. +

+
+
+ + + ErlDrvTimeerl_drv_monotonic_time(ErlDrvTimeUnit time_unit) + Get Erlang Monotonic Time + + +

Arguments:

+ + time_unit + Time unit of returned value. + +

+ Returns + Erlang + monotonic time. Note that it is not uncommon with + negative values. +

+

Returns ERL_DRV_TIME_ERROR if called with an invalid + time unit argument, or if called from a thread that is not a + scheduler thread.

+

See also:

+ + ErlDrvTime + ErlDrvTimeUnit + +
+
+ ErlDrvMutex *erl_drv_mutex_create(char *name) Create a mutex @@ -2469,6 +2334,25 @@ ERL_DRV_MAP int sz + + char *erl_drv_mutex_name(ErlDrvMutex *mtx) + Get name of driver mutex. + + +

Arguments:

+ + mtx + A pointer to an initialized mutex. + +

+ Returns a pointer to the name of the mutex. +

+ +

This function is intended for debugging purposes only.

+
+
+
+ interl_drv_mutex_trylock(ErlDrvMutex *mtx) Try lock a mutex @@ -2510,112 +2394,209 @@ ERL_DRV_MAP int sz - ErlDrvCond *erl_drv_cond_create(char *name) - Create a condition variable + interl_drv_output_term(ErlDrvTermData port, ErlDrvTermData* term, int n) + Send term data from driver to port owner - -

Arguments:

- - name - A string identifying the created condition variable. It - will be used to identify the condition variable in planned - future debug functionality. - - -

This function creates a condition variable and returns a - pointer to it. On failure NULL is returned. The driver - creating the condition variable has the responsibility of - destroying it before the driver is unloaded.

-

This function is thread-safe.

-
-
+ +

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

+

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

+

The term parameter points to an array of + ErlDrvTermData, with n elements. This array + contains terms described in the driver term format. Every + term consists of one to four elements in the array. The + term first has a term type, and then arguments. The + port parameter specifies the sending port.

+

Tuples, maps and lists (with the exception of strings, see below), + are built in reverse polish notation, so that to build a + tuple, the elements are given first, and then the tuple + term, with a count. Likewise for lists and maps.

+

A tuple must be specified with the number of elements. (The + elements precede the ERL_DRV_TUPLE term.)

+

A list must be specified with the number of elements, + including the tail, which is the last term preceding + ERL_DRV_LIST.

+

A map must be specified with the number of key-value pairs N. + The key-value pairs must precede the ERL_DRV_MAP in this order: + key1,value1,key2,value2,...,keyN,valueN. + Duplicate keys are not allowed.

+

The special term ERL_DRV_STRING_CONS is used to + "splice" in a string in a list, a string given this way is + not a list per se, but the elements are elements of the + surrounding list.

+
+Term type            Argument(s)
+===========================================
+ERL_DRV_NIL
+ERL_DRV_ATOM         ErlDrvTermData atom (from driver_mk_atom(char *string))
+ERL_DRV_INT          ErlDrvSInt integer
+ERL_DRV_UINT         ErlDrvUInt integer
+ERL_DRV_INT64        ErlDrvSInt64 *integer_ptr
+ERL_DRV_UINT64       ErlDrvUInt64 *integer_ptr
+ERL_DRV_PORT         ErlDrvTermData port (from driver_mk_port(ErlDrvPort port))
+ERL_DRV_BINARY       ErlDrvBinary *bin, ErlDrvUInt len, ErlDrvUInt offset
+ERL_DRV_BUF2BINARY   char *buf, ErlDrvUInt len
+ERL_DRV_STRING       char *str, int len
+ERL_DRV_TUPLE        int sz
+ERL_DRV_LIST         int sz
+ERL_DRV_PID          ErlDrvTermData pid (from driver_connected(ErlDrvPort port) or driver_caller(ErlDrvPort port))
+ERL_DRV_STRING_CONS  char *str, int len
+ERL_DRV_FLOAT        double *dbl
+ERL_DRV_EXT2TERM     char *buf, ErlDrvUInt len
+ERL_DRV_MAP          int sz
+        
+

The unsigned integer data type ErlDrvUInt and the + signed integer data type ErlDrvSInt are 64 bits wide + on a 64 bit runtime system and 32 bits wide on a 32 bit + runtime system. They were introduced in erts version 5.6, + and replaced some of the int arguments in the list above. +

+

The unsigned integer data type ErlDrvUInt64 and the + signed integer data type ErlDrvSInt64 are always 64 bits + wide. They were introduced in erts version 5.7.4. +

- - voiderl_drv_cond_destroy(ErlDrvCond *cnd) - Destroy a condition variable - - -

Arguments:

- - cnd - A pointer to a condition variable to destroy. - -

This function destroys a condition variable previously - created by - erl_drv_cond_create(). +

To build the tuple {tcp, Port, [100 | Binary]}, the + following call could be made.

+ + +

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

+

The term ERL_DRV_STRING_CONS is a way to construct + strings. It works differently from how ERL_DRV_STRING + works. ERL_DRV_STRING_CONS builds a string list in + reverse order, (as opposed to how ERL_DRV_LIST + works), concatenating the strings added to a list. The tail + must be given before ERL_DRV_STRING_CONS.

+

The ERL_DRV_STRING constructs a string, and ends + it. (So it's the same as ERL_DRV_NIL followed by + ERL_DRV_STRING_CONS.)

+ +

+ +

The ERL_DRV_EXT2TERM term type is used for passing a + term encoded with the + external format, + i.e., a term that has been encoded by + erlang:term_to_binary, + erl_interface, etc. + For example, if binp is a pointer to an ErlDrvBinary + that contains the term {17, 4711} encoded with the + external format + and you want to wrap it in a two tuple with the tag my_tag, + i.e., {my_tag, {17, 4711}}, you can do as follows:

-

This function is thread-safe.

-
-
+ orig_bytes, binp->orig_size + ERL_DRV_TUPLE, 2, + }; + erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0])); + ]]> - - voiderl_drv_cond_signal(ErlDrvCond *cnd) - Signal on a condition variable - - -

Arguments:

- - cnd - A pointer to a condition variable to signal on. - -

This function signals on a condition variable. That is, if - other threads are waiting on the condition variable being - signaled, one of them will be woken. +

To build the map #{key1 => 100, key2 => {200, 300}}, the + following call could be made.

+ + + +

If you want to pass a binary and don't already have the content + of the binary in an ErlDrvBinary, you can benefit from using + ERL_DRV_BUF2BINARY instead of creating an ErlDrvBinary + via driver_alloc_binary() and then pass the binary via + ERL_DRV_BINARY. The runtime system will often allocate + binaries smarter if ERL_DRV_BUF2BINARY is used. + However, if the content of the binary to pass already resides in + an ErlDrvBinary, it is normally better to pass the binary + using ERL_DRV_BINARY and the ErlDrvBinary in question.

-

This function is thread-safe.

-
-
- - - voiderl_drv_cond_broadcast(ErlDrvCond *cnd) - Broadcast on a condition variable - - -

Arguments:

- - cnd - A pointer to a condition variable to broadcast on. - -

This function broadcasts on a condition variable. That is, if - other threads are waiting on the condition variable being - broadcast on, all of them will be woken. +

The ERL_DRV_UINT, ERL_DRV_BUF2BINARY, and + ERL_DRV_EXT2TERM term types were introduced in the 5.6 + version of erts.

-

This function is thread-safe.

+

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

- voiderl_drv_cond_wait(ErlDrvCond *cnd, ErlDrvMutex *mtx) - Wait on a condition variable + interl_drv_putenv(const char *key, char *value) + Set the value of an environment variable - +

Arguments:

- cnd - A pointer to a condition variable to wait on. - mtx - A pointer to a mutex to unlock while waiting. - - + key + A null terminated string containing the + name of the environment variable. + value + A null terminated string containing the + new value of the environment variable. -

This function waits on a condition variable. The calling - thread is blocked until another thread wakes it by signaling - or broadcasting on the condition variable. Before the calling - thread is blocked it unlocks the mutex passed as argument, and - when the calling thread is woken it locks the same mutex before - returning. That is, the mutex currently has to be locked by - the calling thread when calling this function. +

This function sets the value of an environment variable. + It returns 0 on success, and a value != 0 on + failure.

-

erl_drv_cond_wait() might return even though - no-one has signaled or broadcast on the condition - variable. Code calling erl_drv_cond_wait() should - always be prepared for erl_drv_cond_wait() - returning even though the condition that the thread was - waiting for hasn't occurred. That is, when returning from - erl_drv_cond_wait() always check if the condition - has occurred, and if not call erl_drv_cond_wait() - again. -

+

The result of passing the empty string ("") as a value + is platform dependent. On some platforms the value of the + variable is set to the empty string, on others, the + environment variable is removed.

+
+

Do not use libc's putenv or similar + C library interfaces from a driver. +

This function is thread-safe.

@@ -2659,6 +2640,25 @@ ERL_DRV_MAP int sz
+ + char *erl_drv_rwlock_name(ErlDrvRWLock *rwlck) + Get name of driver mutex. + + +

Arguments:

+ + rwlck + A pointer to an initialized r/w-lock. + +

+ Returns a pointer to the name of the r/w-lock. +

+ +

This function is intended for debugging purposes only.

+
+
+
+ voiderl_drv_rwlock_rlock(ErlDrvRWLock *rwlck) Read lock an rwlock @@ -2682,29 +2682,6 @@ ERL_DRV_MAP int sz - - interl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck) - Try to read lock an rwlock - - -

Arguments:

- - rwlck - A pointer to an rwlock to try to read lock. - -

This function tries to read lock an rwlock. If successful - 0, is returned; otherwise, EBUSY is returned. - A thread which currently has read or read/write locked the - rwlock may not try to lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

-

This function is thread-safe.

-
-
- voiderl_drv_rwlock_runlock(ErlDrvRWLock *rwlck) Read unlock an rwlock @@ -2745,29 +2722,6 @@ ERL_DRV_MAP int sz - - interl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck) - Try to read/write lock an rwlock - - -

Arguments:

- - rwlck - A pointer to an rwlock to try to read/write lock. - -

This function tries to read/write lock an rwlock. If successful - 0, is returned; otherwise, EBUSY is returned. - A thread which currently has read or read/write locked the - rwlock may not try to lock the same rwlock again. -

-

If you leave an rwlock locked in an emulator thread - when you let the thread out of your control, you will - very likely deadlock the whole emulator. -

-

This function is thread-safe.

-
-
- voiderl_drv_rwlock_rwunlock(ErlDrvRWLock *rwlck) Read/Write unlock an rwlock @@ -2786,276 +2740,200 @@ ERL_DRV_MAP int sz - interl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key) - Create a thread specific data key + interl_drv_rwlock_tryrlock(ErlDrvRWLock *rwlck) + Try to read lock an rwlock - +

Arguments:

- name - A string identifying the created key. It will be used - to identify the key in planned future debug - functionality. - - key - A pointer to a thread specific data key variable. + rwlck + A pointer to an rwlock to try to read lock. -

This function creates a thread specific data key. On success - 0 is returned; otherwise, an errno value is returned - to indicate the error. The driver creating the key has the - responsibility of destroying it before the driver is unloaded. +

This function tries to read lock an rwlock. If successful + 0, is returned; otherwise, EBUSY is returned. + A thread which currently has read or read/write locked the + rwlock may not try to lock the same rwlock again.

+

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator. +

This function is thread-safe.

- voiderl_drv_tsd_key_destroy(ErlDrvTSDKey key) - Destroy a thread specific data key + interl_drv_rwlock_tryrwlock(ErlDrvRWLock *rwlck) + Try to read/write lock an rwlock - +

Arguments:

- key - A thread specific data key to destroy. + rwlck + A pointer to an rwlock to try to read/write lock. -

This function destroys a thread specific data key - previously created by - erl_drv_tsd_key_create(). - All thread specific data using this key in all threads - have to be cleared (see - erl_drv_tsd_set()) - prior to the call to erl_drv_tsd_key_destroy(). +

This function tries to read/write lock an rwlock. If successful + 0, is returned; otherwise, EBUSY is returned. + A thread which currently has read or read/write locked the + rwlock may not try to lock the same rwlock again.

-

A destroyed key is very likely to be reused soon. - Therefore, if you fail to clear the thread specific - data using this key in a thread prior to destroying - the key, you will very likely get unexpected - errors in other parts of the system. +

If you leave an rwlock locked in an emulator thread + when you let the thread out of your control, you will + very likely deadlock the whole emulator.

This function is thread-safe.

- voiderl_drv_tsd_set(ErlDrvTSDKey key, void *data) - Set thread specific data + interl_drv_send_term(ErlDrvTermData port, ErlDrvTermData receiver, ErlDrvTermData* term, int n) + Send term data to other process than port owner process - -

Arguments:

- - key - A thread specific data key. - data - A pointer to data to associate with key - in calling thread. - - -

This function sets thread specific data associated with - key for the calling thread. You are only allowed to set - thread specific data for threads while they are fully under your - control. For example, if you set thread specific data in a thread - calling a driver call-back function, it has to be cleared, i.e. - set to NULL, before returning from the driver call-back - function. -

-

If you fail to clear thread specific data in an - emulator thread before letting it out of your control, - you might not ever be able to clear this data with - later unexpected errors in other parts of the system as - a result. -

-

This function is thread-safe.

+ +

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.

- void *erl_drv_tsd_get(ErlDrvTSDKey key) - Get thread specific data + voiderl_drv_set_os_pid(ErlDrvPort port, ErlDrvSInt pid) + Set the os_pid for the port - +

Arguments:

- key - A thread specific data key. - -

This function returns the thread specific data - associated with key for the calling thread. - If no data has been associated with key for - the calling thread, NULL is returned. -

-

This function is thread-safe.

+ port + The port handle of the port (driver instance) to set the pid on. + + pid + The pid to set. + +

+ Set the os_pid seen when doing erlang:port_info/2 on this port. +

- interl_drv_putenv(const char *key, char *value) - Set the value of an environment variable + interl_drv_thread_create(char *name, + ErlDrvTid *tid, + void * (*func)(void *), + void *arg, + ErlDrvThreadOpts *opts) + Create a thread - +

Arguments:

- key - A null terminated string containing the - name of the environment variable. - value - A null terminated string containing the - new value of the environment variable. + name + A string identifying the created thread. It will be used + to identify the thread in planned future debug + functionality. + + tid + A pointer to a thread identifier variable. + func + A pointer to a function to execute in the created thread. + arg + A pointer to argument to the func function. + opts + A pointer to thread options to use or NULL. -

This function sets the value of an environment variable. - It returns 0 on success, and a value != 0 on - failure. +

This function creates a new thread. On success 0 is returned; + otherwise, an errno value is returned to indicate the error. + The newly created thread will begin executing in the function pointed + to by func, and func will be passed arg as + argument. When erl_drv_thread_create() returns the thread + identifier of the newly created thread will be available in + *tid. opts can be either a NULL pointer, or a + pointer to an + ErlDrvThreadOpts + structure. If opts is a NULL pointer, default options + will be used; otherwise, the passed options will be used.

-

The result of passing the empty string ("") as a value - is platform dependent. On some platforms the value of the - variable is set to the empty string, on others, the - environment variable is removed.

-
-

Do not use libc's putenv or similar - C library interfaces from a driver. +

You are not allowed to allocate the + ErlDrvThreadOpts + structure by yourself. It has to be allocated and + initialized by + erl_drv_thread_opts_create(). +

+

The created thread will terminate either when func returns + or if + erl_drv_thread_exit() + is called by the thread. The exit value of the thread is either + returned from func or passed as argument to + erl_drv_thread_exit(). + The driver creating the thread has the responsibility of joining the + thread, via + erl_drv_thread_join(), + before the driver is unloaded. It is not possible to create + "detached" threads, i.e., threads that don't need to be joined. +

+

All created threads need to be joined by the driver before + it is unloaded. If the driver fails to join all threads + created before it is unloaded, the runtime system will + most likely crash when the code of the driver is unloaded.

This function is thread-safe.

+ - interl_drv_getenv(const char *key, char *value, size_t *value_size) - Get the value of an environment variable + voiderl_drv_thread_exit(void *exit_value) + Terminate calling thread - +

Arguments:

- key - A null terminated string containing the - name of the environment variable. - value - A pointer to an output buffer. - value_size - A pointer to an integer. The integer is both used for - passing input and output sizes (see below). - + exit_value + A pointer to an exit value or NULL. -

This function retrieves the value of an environment variable. - When called, *value_size should contain the size of - the value buffer. On success 0 is returned, - the value of the environment variable has been written to - the value buffer, and *value_size contains the - string length (excluding the terminating null character) of - the value written to the value buffer. On failure, - i.e., no such environment variable was found, a value less than - 0 is returned. When the size of the value - buffer is too small, a value greater than 0 is returned - and *value_size has been set to the buffer size needed. +

This function terminates the calling thread with the exit + value passed as argument. You are only allowed to terminate + threads created with + erl_drv_thread_create(). + The exit value can later be retrieved by another thread via + erl_drv_thread_join().

-

Do not use libc's getenv or similar - C library interfaces from a driver. -

This function is thread-safe.

+ - interl_drv_consume_timeslice(ErlDrvPort port, int percent) - Give the runtime system a hint about how much CPU time the - current driver callback call has consumed + interl_drv_thread_join(ErlDrvTid tid, void **exit_value) + Join with another thread - +

Arguments:

- port - Port handle of the executing port. - percent - Approximate consumed fraction of a full - time-slice in percent. + tid + The thread identifier of the thread to join. + exit_value + A pointer to a pointer to an exit value, or NULL. -

Give the runtime system a hint about how much CPU time the - current driver callback call has consumed since last hint, or - since the start of the callback if no previous hint has been given. - The time is given as a fraction, in percent, of a full time-slice - that a port is allowed to execute before it should surrender the - CPU to other runnable ports or processes. Valid range is - [1, 100]. The scheduling time-slice is not an exact entity, - but can usually be approximated to about 1 millisecond.

- -

Note that it is up to the runtime system to determine if and - how to use this information. Implementations on some platforms - may use other means in order to determine the consumed fraction - of the time-slice. Lengthy driver callbacks should regardless of - this frequently call the erl_drv_consume_timeslice() - function in order to determine if it is allowed to continue - execution or not.

- -

erl_drv_consume_timeslice() returns a non-zero value - if the time-slice has been exhausted, and zero if the callback is - allowed to continue execution. If a non-zero value is - returned the driver callback should return as soon as possible in - order for the port to be able to yield.

- -

This function is provided to better support co-operative scheduling, - improve system responsiveness, and to make it easier to prevent - misbehaviors of the VM due to a port monopolizing a scheduler thread. - It can be used when dividing length work into a number of repeated - driver callback calls without the need to use threads. Also see the - important warning text at the - beginning of this document.

+

This function joins the calling thread with another thread, i.e., + the calling thread is blocked until the thread identified by + tid has terminated. On success 0 is returned; + otherwise, an errno value is returned to indicate the error. + A thread can only be joined once. The behavior of joining + more than once is undefined, an emulator crash is likely. If + exit_value == NULL, the exit value of the terminated thread + will be ignored; otherwise, the exit value of the terminated thread + will be stored at *exit_value. +

+

This function is thread-safe.

- - char *erl_drv_cond_name(ErlDrvCond *cnd) - Get name of driver mutex. - - -

Arguments:

- - cnd - A pointer to an initialized condition. - -

- Returns a pointer to the name of the condition. -

- -

This function is intended for debugging purposes only.

-
-
-
- - - char *erl_drv_mutex_name(ErlDrvMutex *mtx) - Get name of driver mutex. - - -

Arguments:

- - mtx - A pointer to an initialized mutex. - -

- Returns a pointer to the name of the mutex. -

- -

This function is intended for debugging purposes only.

-
-
-
- - - char *erl_drv_rwlock_name(ErlDrvRWLock *rwlck) - Get name of driver mutex. - - -

Arguments:

- - rwlck - A pointer to an initialized r/w-lock. - -

- Returns a pointer to the name of the r/w-lock. -

- -

This function is intended for debugging purposes only.

-
-
-
- char *erl_drv_thread_name(ErlDrvTid tid) Get name of driver mutex. @@ -3075,32 +2953,64 @@ ERL_DRV_MAP int sz - - ErlDrvTimeerl_drv_monotonic_time(ErlDrvTimeUnit time_unit) - Get Erlang Monotonic Time - - -

Arguments:

- - time_unit - Time unit of returned value. - -

- Returns - Erlang - monotonic time. Note that it is not uncommon with - negative values. -

-

Returns ERL_DRV_TIME_ERROR if called with an invalid - time unit argument, or if called from a thread that is not a - scheduler thread.

-

See also:

- - ErlDrvTime - ErlDrvTimeUnit - -
-
+ + ErlDrvThreadOpts *erl_drv_thread_opts_create(char *name) + Create thread options + + +

Arguments:

+ + name + A string identifying the created thread options. It will be used + to identify the thread options in planned future debug + functionality. + + +

This function allocates and initialize a thread option + structure. On failure NULL is returned. A thread option + structure is used for passing options to + erl_drv_thread_create(). + If the structure isn't modified before it is passed to + erl_drv_thread_create(), + the default values will be used. +

+

You are not allowed to allocate the + ErlDrvThreadOpts + structure by yourself. It has to be allocated and + initialized by erl_drv_thread_opts_create(). +

+

This function is thread-safe.

+
+
+ + + voiderl_drv_thread_opts_destroy(ErlDrvThreadOpts *opts) + Destroy thread options + + +

Arguments:

+ + opts + A pointer to thread options to destroy. + +

This function destroys thread options previously created by + erl_drv_thread_opts_create(). +

+

This function is thread-safe.

+
+
+ + + ErlDrvTiderl_drv_thread_self(void) + Get the thread identifier of the current thread + + +

This function returns the thread identifier of the + calling thread. +

+

This function is thread-safe.

+
+
ErlDrvTimeerl_drv_time_offset(ErlDrvTimeUnit time_unit) @@ -3128,33 +3038,180 @@ ERL_DRV_MAP int sz - - ErlDrvTimeerl_drv_convert_time_unit(ErlDrvTime val, ErlDrvTimeUnit from, ErlDrvTimeUnit to) - Convert time unit of a time value - - -

Arguments:

- - val - Value to convert time unit for. - from - Time unit of val. - to - Time unit of returned value. - -

Converts the val value of time unit from to - the corresponding value of time unit to. The result is - rounded using the floor function.

-

Returns ERL_DRV_TIME_ERROR if called with an invalid - time unit argument.

-

See also:

- - ErlDrvTime - ErlDrvTimeUnit - -
-
+ + void *erl_drv_tsd_get(ErlDrvTSDKey key) + Get thread specific data + + +

Arguments:

+ + key + A thread specific data key. + +

This function returns the thread specific data + associated with key for the calling thread. + If no data has been associated with key for + the calling thread, NULL is returned. +

+

This function is thread-safe.

+
+
+ + + interl_drv_tsd_key_create(char *name, ErlDrvTSDKey *key) + Create a thread specific data key + + +

Arguments:

+ + name + A string identifying the created key. It will be used + to identify the key in planned future debug + functionality. + + key + A pointer to a thread specific data key variable. + +

This function creates a thread specific data key. On success + 0 is returned; otherwise, an errno value is returned + to indicate the error. The driver creating the key has the + responsibility of destroying it before the driver is unloaded. +

+

This function is thread-safe.

+
+
+ + + voiderl_drv_tsd_key_destroy(ErlDrvTSDKey key) + Destroy a thread specific data key + + +

Arguments:

+ + key + A thread specific data key to destroy. + +

This function destroys a thread specific data key + previously created by + erl_drv_tsd_key_create(). + All thread specific data using this key in all threads + have to be cleared (see + erl_drv_tsd_set()) + prior to the call to erl_drv_tsd_key_destroy(). +

+

A destroyed key is very likely to be reused soon. + Therefore, if you fail to clear the thread specific + data using this key in a thread prior to destroying + the key, you will very likely get unexpected + errors in other parts of the system. +

+

This function is thread-safe.

+
+
+ + + voiderl_drv_tsd_set(ErlDrvTSDKey key, void *data) + Set thread specific data + + +

Arguments:

+ + key + A thread specific data key. + data + A pointer to data to associate with key + in calling thread. + + +

This function sets thread specific data associated with + key for the calling thread. You are only allowed to set + thread specific data for threads while they are fully under your + control. For example, if you set thread specific data in a thread + calling a driver call-back function, it has to be cleared, i.e. + set to NULL, before returning from the driver call-back + function. +

+

If you fail to clear thread specific data in an + emulator thread before letting it out of your control, + you might not ever be able to clear this data with + later unexpected errors in other parts of the system as + a result. +

+

This function is thread-safe.

+
+
+ + + char *erl_errno_id(int error) + Get erlang error atom name from error number + + +

This function returns the atom name of the erlang error, + given the error number in error. Error atoms are: + einval, enoent, etc. It can be used to make + error terms from the driver.

+
+
+ + + intremove_driver_entry(ErlDrvEntry *de) + Remove a driver entry + + +

This function removes a driver entry de previously + added with add_driver_entry.

+

Driver entries added by the erl_ddll erlang interface can + not be removed by using this interface.

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

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

+

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

+

If the + + has been set in the + driver_entry, + data can be forced into the driver via + port_command(Port, Data, [force]) + even though the driver has signaled that it is busy. +

+

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

+
+
+ + voidset_port_control_flags(ErlDrvPort port, int flags) + Set flags on how to handle control entry function + + +

This function sets flags for how the control driver entry + function will return data to the port owner process. (The + control function is called from port_control/3 + in erlang.)

+

Currently there are only two meaningful values for + flags: 0 means that data is returned in a list, and + PORT_CONTROL_FLAG_BINARY means data is returned as + a binary from control.

+
+
SEE ALSO -- cgit v1.2.3