From 57c3246511434f42214e113b8902af10ab9cca49 Mon Sep 17 00:00:00 2001 From: xsipewe Date: Tue, 21 Jun 2016 15:50:34 +0200 Subject: erts: Editorial changes --- erts/doc/src/driver_entry.xml | 639 +++++++++++++++++++++++------------------- 1 file changed, 349 insertions(+), 290 deletions(-) (limited to 'erts/doc/src/driver_entry.xml') diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index ae7f264d0c..dea003f091 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -33,55 +33,64 @@ driver_entry.xml driver_entry - The driver-entry structure used by erlang drivers. + The driver-entry structure used by Erlang drivers. -

Use this functionality with extreme care!

+ +

Use this functionality with extreme care.

A driver callback is executed as a direct extension of the - native code of the VM. Execution is not made in a safe environment. - The VM can not provide the same services as provided when - executing Erlang code, such as preemptive scheduling or memory - protection. If the driver callback function doesn't behave well, - the whole VM will misbehave.

- -

A driver callback that crash will crash the whole VM.

-

An erroneously implemented driver callback might cause - a VM internal state inconsistency which may cause a crash of the VM, - or miscellaneous misbehaviors of the VM at any point after the call - to the driver callback.

-

A driver callback that do - lengthy work - before returning will degrade responsiveness of the VM, - and may cause miscellaneous strange behaviors. Such strange behaviors - include, but are not limited to, extreme memory usage, and bad load - balancing between schedulers. Strange behaviors that might occur due - to lengthy work may also vary between OTP releases.

+ native code of the VM. Execution is not made in a safe environment. + The VM cannot provide the same services as provided when + executing Erlang code, such as pre-emptive scheduling or memory + protection. If the driver callback function does not behave well, + the whole VM will misbehave.

+ + +

A driver callback that crash will crash the whole VM.

+
+ +

An erroneously implemented driver callback can cause a VM + internal state inconsistency, which can cause a crash of the VM, + or miscellaneous misbehaviors of the VM at any point after the + call to the driver callback.

+
+ +

A driver callback doing + lengthy work + before returning degrades responsiveness of the VM, and can cause + miscellaneous strange behaviors. Such strange behaviors + include, but are not limited to, extreme memory usage, and bad + load balancing between schedulers. Strange behaviors that can + occur because of lengthy work can also vary between Erlang/OTP + releases.

+
-
-

- As of erts version 5.9 (OTP release R15B) the driver interface + + +

As from ERTS 5.9 (Erlang/OTP R15B) the driver interface has been changed with larger types for the callbacks - output, - control and - call. + output, + control, and + call. See driver version management in - erl_driver. -

+ erl_driver.

+

Old drivers (compiled with an erl_driver.h from an - earlier erts version than 5.9) have to be updated and have - to use the extended interface (with - version management - ).

+ ERTS version earlier than 5.9) must be updated and have + to use the extended interface (with + version management + ).

-

The driver_entry structure is a C struct that all erlang - drivers define. It contains entry points for the erlang driver - that are called by the erlang emulator when erlang code accesses + +

The driver_entry structure is a C struct that all Erlang + drivers define. It contains entry points for the Erlang driver, + which are called by the Erlang emulator when Erlang code accesses the driver.

-

- - The erl_driver driver + +

+ The erl_driver driver API functions need a port handle that identifies the driver instance (and the port in the emulator). This is only passed to the start function, but @@ -90,416 +99,466 @@ common practice is to have the start function allocate some application-defined structure and stash the port handle in it, to use it later with the driver API functions.

-

The driver call-back functions are called synchronously from the - erlang emulator. If they take too long before completing, they - can cause timeouts in the emulator. Use the queue or - asynchronous calls if necessary, since the emulator must be + +

The driver callback functions are called synchronously from the + Erlang emulator. If they take too long before completing, they + can cause time-outs in the emulator. Use the queue or + asynchronous calls if necessary, as the emulator must be responsive.

-

The driver structure contains the name of the driver and some - 15 function pointers. These pointers are called at different + +

The driver structure contains the driver name and some + 15 function pointers, which are called at different times by the emulator.

+

The only exported function from the driver is driver_init. This function returns the driver_entry structure that points to the other functions in the driver. The - driver_init function is declared with a macro - DRIVER_INIT(drivername). (This is because different OS's - have different names for it.)

-

When writing a driver in C++, the driver entry should be of - "C" linkage. One way to do this is to put this line - somewhere before the driver entry: - extern "C" DRIVER_INIT(drivername);.

+ driver_init function is declared with a macro, + DRIVER_INIT(drivername). (This is because different + operating systems have different names for it.)

+ +

When writing a driver in C++, the driver entry is to be of + "C" linkage. One way to do this is to put the + following line somewhere before the driver entry:

+ +
+extern "C" DRIVER_INIT(drivername);
+

When the driver has passed the driver_entry over to the emulator, the driver is not allowed to modify the driver_entry.

-

If compiling a driver for static inclusion via --enable-static-drivers you - have to define STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.

+ +

If compiling a driver for static inclusion through + --enable-static-drivers, you must define + STATIC_ERLANG_DRIVER before the DRIVER_INIT declaration.

+ -

Do not declare the driver_entry const. This since the emulator needs to - modify the handle, and the handle2 - fields. A statically allocated, and const - declared driver_entry may be located in - read only memory which will cause the emulator - to crash.

+

Do not declare the driver_entry const. + This because the emulator must + modify the handle and the handle2 + fields. A statically allocated, and const-declared + driver_entry can be located in + read-only memory, which causes the emulator to crash.

- DATA TYPES - - ErlDrvEntry - -

+ Data Types +

ErlDrvEntry

typedef struct erl_drv_entry { - int (*init)(void); /* called at system start up for statically + int (*init)(void); /* Called at system startup for statically linked drivers, and after loading for - dynamically loaded drivers */ - + dynamically loaded drivers */ #ifndef ERL_SYS_DRV ErlDrvData (*start)(ErlDrvPort port, char *command); - /* called when open_port/2 is invoked. - return value -1 means failure. */ + /* Called when open_port/2 is invoked, + return value -1 means failure */ #else ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts); - /* special options, only for system driver */ + /* Special options, only for system driver */ #endif void (*stop)(ErlDrvData drv_data); - /* called when port is closed, and when the - emulator is halted. */ + /* Called when port is closed, and when the + emulator is halted */ void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len); - /* called when we have output from erlang to + /* Called when we have output from Erlang to the port */ void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when we have input from one of + /* Called when we have input from one of the driver's handles */ void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event); - /* called when output is possible to one of + /* Called when output is possible to one of the driver's handles */ - char *driver_name; /* name supplied as command - in open_port XXX ? */ - void (*finish)(void); /* called before unloading the driver - - DYNAMIC DRIVERS ONLY */ - void *handle; /* Reserved -- Used by emulator internally */ + char *driver_name; /* Name supplied as command in + erlang:open_port/2 */ + void (*finish)(void); /* Called before unloading the driver - + dynamic drivers only */ + void *handle; /* Reserved, used by emulator internally */ ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen); - /* "ioctl" for drivers - invoked by + /* "ioctl" for drivers - invoked by port_control/3 */ - void (*timeout)(ErlDrvData drv_data); /* Handling of timeout in driver */ + void (*timeout)(ErlDrvData drv_data); + /* Handling of time-out in driver */ void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); - /* called when we have output from erlang + /* Called when we have output from Erlang to the port */ void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); void (*flush)(ErlDrvData drv_data); - /* called when the port is about to be - closed, and there is data in the - driver queue that needs to be flushed + /* Called when the port is about to be + closed, and there is data in the + driver queue that must be flushed before 'stop' can be called */ ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags); /* Works mostly like 'control', a synchronous - call into the driver. */ + call into the driver */ void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data); - /* Called when an event selected by + /* Called when an event selected by driver_event() has occurred */ int extended_marker; /* ERL_DRV_EXTENDED_MARKER */ int major_version; /* ERL_DRV_EXTENDED_MAJOR_VERSION */ int minor_version; /* ERL_DRV_EXTENDED_MINOR_VERSION */ int driver_flags; /* ERL_DRV_FLAGs */ - void *handle2; /* Reserved -- Used by emulator internally */ + void *handle2; /* Reserved, used by emulator internally */ void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor); /* Called when a process monitor fires */ void (*stop_select)(ErlDrvEvent event, void* reserved); /* Called to close an event object */ - } ErlDrvEntry; - -

+ } ErlDrvEntry; - int (*init)(void) - -

This is called directly after the driver has been loaded by - erl_ddll:load_driver/2. (Actually when the driver is - added to the driver list.) The driver should return 0, or if - the driver can't initialize, -1.

+ int (*init)(void) + +

Called directly after the driver has been loaded by + + erl_ddll:load_driver/2 (actually when the driver is + added to the driver list). The driver is to return 0, or, if + the driver cannot initialize, -1.

- ErlDrvData (*start)(ErlDrvPort port, char* command) + + ErlDrvData (*start)(ErlDrvPort port, char* command) -

This is called when the driver is instantiated, when - open_port/2 is called. The driver should return a - number >= 0 or a pointer, or if the driver can't be started, - one of three error codes should be returned:

-

ERL_DRV_ERROR_GENERAL - general error, no error code

-

ERL_DRV_ERROR_ERRNO - error with error code in errno

-

ERL_DRV_ERROR_BADARG - error, badarg

-

If an error code is returned, the port isn't started.

+

Called when the driver is instantiated, when + + erlang:open_port/2 is called. + The driver is to return a number >= 0 or a pointer, or, if the + driver cannot be started, one of three error codes:

+ + ERL_DRV_ERROR_GENERAL + General error, no error code + ERL_DRV_ERROR_ERRNO + Error with error code in errno + ERL_DRV_ERROR_BADARG + Error, badarg + +

If an error code is returned, the port is not started.

- void (*stop)(ErlDrvData drv_data) + void (*stop)(ErlDrvData drv_data) -

This is called when the port is closed, with - port_close/1 or Port ! {self(), close}. Note - that terminating the port owner process also closes the +

Called when the port is closed, with + + erlang:port_close/1 or Port ! {self(), close}. + Notice that terminating the port owner process also closes the port. If drv_data is a pointer to memory allocated in - start, then stop is the place to deallocate that - memory.

+ start, then stop is the place to deallocate that + memory.

- void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) + + void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len) + -

This is called when an erlang process has sent data to the - port. The data is pointed to by buf, and is - len bytes. Data is sent to the port with Port ! {self(), {command, Data}}, or with - port_command/2. Depending on how the port was opened, - it should be either a list of integers 0...255 or a - binary. See open_port/3 and port_command/2.

+

Called when an Erlang process has sent data to the port. The data is + pointed to by buf, and is len bytes. Data is sent to + the port with Port ! {self(), {command, Data}} or with + erlang:port_command/2. Depending on how the port was + opened, it is to be either a list of integers 0...255 or a + binary. See + erlang:open_port/2 and + + erlang:port_command/2.

- - void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event) - - void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event) + + void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event) + + + + void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event) + -

This is called when a driver event (given in the - event parameter) is signaled. This is used to help - asynchronous drivers "wake up" when something happens.

-

On unix the event is a pipe or socket handle (or +

Called when a driver event (specified in parameter + event) is signaled. This is used to help + asynchronous drivers "wake up" when something occurs.

+

On Unix the event is a pipe or socket handle (or something that the select system call understands).

-

On Windows the event is an Event or Semaphore (or - something that the WaitForMultipleObjects API +

On Windows the event is an Event or Semaphore + (or something that the WaitForMultipleObjects API function understands). (Some trickery in the emulator allows more than the built-in limit of 64 Events to be used.)

To use this with threads and asynchronous routines, create a - pipe on unix and an Event on Windows. When the routine + pipe on Unix and an Event on Windows. When the routine completes, write to the pipe (use SetEvent on - Windows), this will make the emulator call + Windows), this makes the emulator call ready_input or ready_output.

-

Spurious events may happen. That is, calls to ready_input - or ready_output even though no real events are signaled. In - reality it should be rare (and OS dependant), but a robust driver +

False events can occur. That is, calls to ready_input + or ready_output although no real events are signaled. In + reality, it is rare (and OS-dependant), but a robust driver must nevertheless be able to handle such cases.

- char *driver_name + char *driver_name -

This is the name of the driver, it must correspond to the - atom used in open_port, and the name of the driver +

The driver name. It must correspond to the atom used in + + erlang:open_port/2, and the name of the driver library file (without the extension).

- void (*finish)(void) + void (*finish)(void) -

This function is called by the erl_ddll driver when the +

Called by the erl_ddll driver when the driver is unloaded. (It is only called in dynamic drivers.)

The driver is only unloaded as a result of calling - unload_driver/1, or when the emulator halts.

+ + erl_ddll:unload_driver/1, + or when the emulator halts.

- void *handle + void *handle

This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the driver_entry isn't declared const.

+ emulator will modify this field, so it is important + that the driver_entry is not declared const.

- ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) + + ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command, + char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen) -

This is a special routine invoked with the erlang function - port_control/3. It works a little like an "ioctl" for - erlang drivers. The data given to port_control/3 - arrives in buf and len. The driver may send +

A special routine invoked with + + erlang:port_control/3. + It works a little like an "ioctl" for + Erlang drivers. The data specified to port_control/3 + arrives in buf and len. The driver can send data back, using *rbuf and rlen.

This is the fastest way of calling a driver and get a - response. It won't make any context switch in the erlang - emulator, and requires no message passing. It is suitable - for calling C function to get faster execution, when erlang + response. It makes no context switch in the Erlang + emulator and requires no message passing. It is suitable + for calling C function to get faster execution, when Erlang is too slow.

-

If the driver wants to return data, it should return it in +

If the driver wants to return data, it is to return it in rbuf. When control is called, *rbuf points to a default buffer of rlen bytes, which - can be used to return data. Data is returned different depending on + can be used to return data. Data is returned differently depending on the port control flags (those that are set with - set_port_control_flags). -

+ + erl_driver:set_port_control_flags).

If the flag is set to PORT_CONTROL_FLAG_BINARY, - a binary will be returned. Small binaries can be returned by writing - the raw data into the default buffer. A binary can also be - returned by setting *rbuf to point to a binary allocated with - driver_alloc_binary. - This binary will be freed automatically after control has returned. + a binary is returned. Small binaries can be returned by writing + the raw data into the default buffer. A binary can also be + returned by setting *rbuf to point to a binary allocated with + + erl_driver:driver_alloc_binary. + This binary is freed automatically after control has returned. The driver can retain the binary for read only access with - driver_binary_inc_refc to be freed later with - driver_free_binary. - It is never allowed to alter the binary after control has returned. - If *rbuf is set to NULL, an empty list will be returned. -

+ + erl_driver:driver_binary_inc_refc to be freed later + with + erl_driver:driver_free_binary. + It is never allowed to change the binary after control has + returned. If *rbuf is set to NULL, an empty list is + returned.

If the flag is set to 0, data is returned as a list of integers. Either use the default buffer or set *rbuf to point to a larger buffer allocated with - driver_alloc. - The buffer will be freed automatically after control has returned.

+ + erl_driver:driver_alloc. The + buffer is freed automatically after control has returned.

Using binaries is faster if more than a few bytes are returned.

-

The return value is the number of bytes returned in - *rbuf.

+

The return value is the number of bytes returned in *rbuf.

- - void (*timeout)(ErlDrvData drv_data) + void (*timeout)(ErlDrvData drv_data) + -

This function is called any time after the driver's timer - reaches 0. The timer is activated with - driver_set_timer. There are no priorities or ordering - among drivers, so if several drivers time out at the same - time, any one of them is called first.

+

Called any time after the driver's timer reaches 0. + The timer is activated with + + erl_driver:driver_set_timer. No priorities or + ordering exist among drivers, so if several drivers time out at + the same time, anyone of them is called first.

- - void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev) + + void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev) -

This function is called whenever the port is written to. If +

Called whenever the port is written to. If it is NULL, the output function is called - instead. This function is faster than output, because + instead. This function is faster than output, as it takes an ErlIOVec directly, which requires no - copying of the data. The port should be in binary mode, see - open_port/2.

-

The ErlIOVec contains both a SysIOVec, + copying of the data. The port is to be in binary mode, see + + erlang:open_port/2.

+

ErlIOVec contains both a SysIOVec, suitable for writev, and one or more binaries. If - these binaries should be retained, when the driver returns - from outputv, they can be queued (using driver_enq_bin - for instance), or if they are kept in a static or global + these binaries are to be retained when the driver returns + from outputv, they can be queued (using, for example, + + erl_driver:driver_enq_bin) + or, if they are kept in a static or global variable, the reference counter can be incremented.

- void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data) + + void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData + thread_data) -

This function is called after an asynchronous call has - completed. The asynchronous call is started with driver_async. - This function is called from the erlang emulator thread, as +

Called after an asynchronous call has completed. + The asynchronous call is started with + + erl_driver:driver_async. + This function is called from the Erlang emulator thread, as opposed to the asynchronous function, which is called in - some thread (if multithreading is enabled).

+ some thread (if multi-threading is enabled).

+
+ void (*flush)(ErlDrvData drv_data) + +

Called when the port is about to be closed, + and there is data in the driver queue that must be flushed + before 'stop' can be called.

- ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen, unsigned int *flags) + ErlDrvSSizeT (*call)(ErlDrvData drv_data, + unsigned int command, char *buf, ErlDrvSizeT len, char **rbuf, + ErlDrvSizeT rlen, unsigned int *flags) -

This function is called from erlang:port_call/3. It - works a lot like the control call-back, but uses the +

Called from + erlang:port_call/3. + It works a lot like the control callback, but uses the external term format for input and output.

command is an integer, obtained from the call from - erlang (the second argument to erlang:port_call/3).

+ Erlang (the second argument to erlang:port_call/3).

buf and len provide the arguments to the call (the third argument to erlang:port_call/3). They can be decoded using ei functions.

rbuf points to a return buffer, rlen bytes - long. The return data should be a valid erlang term in the - external (binary) format. This is converted to an erlang + long. The return data is to be a valid Erlang term in the + external (binary) format. This is converted to an Erlang term and returned by erlang:port_call/3 to the - caller. If more space than rlen bytes is needed to + caller. If more space than rlen bytes is needed to return data, *rbuf can be set to memory allocated with - driver_alloc. This memory will be freed automatically - after call has returned.

+ + erl_driver:driver_alloc. + This memory is freed automatically after call has returned.

The return value is the number of bytes returned in *rbuf. If ERL_DRV_ERROR_GENERAL is returned - (or in fact, anything < 0), erlang:port_call/3 will - throw a BAD_ARG.

+ (or in fact, anything < 0), erlang:port_call/3 + throws a BAD_ARG.

- void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data) + void (*event)(ErlDrvData drv_data, ErlDrvEvent event, + ErlDrvEventData event_data)

Intentionally left undocumented.

- int extended_marker + int extended_marker -

- This field should either be equal to ERL_DRV_EXTENDED_MARKER +

This field is either to be equal to ERL_DRV_EXTENDED_MARKER or 0. An old driver (not aware of the extended driver - interface) should set this field to 0. If this field is - equal to 0, all the fields following this field also - have to be 0, or NULL in case it is a - pointer field. -

+ interface) is to set this field to 0. If this field is + 0, all the following fields must also be 0, + or NULL if it is a pointer field.

- int major_version + int major_version -

This field should equal ERL_DRV_EXTENDED_MAJOR_VERSION if - the extended_marker field equals +

This field is to equal ERL_DRV_EXTENDED_MAJOR_VERSION if + field extended_marker equals ERL_DRV_EXTENDED_MARKER.

- int minor_version + int minor_version -

- This field should equal ERL_DRV_EXTENDED_MINOR_VERSION if - the extended_marker field equals - ERL_DRV_EXTENDED_MARKER. -

+

This field is to equal ERL_DRV_EXTENDED_MINOR_VERSION if + field extended_marker equals + ERL_DRV_EXTENDED_MARKER.

- - int driver_flags + int driver_flags

This field is used to pass driver capability and other - information to the runtime system. If the - extended_marker field equals ERL_DRV_EXTENDED_MARKER, - it should contain 0 or driver flags (ERL_DRV_FLAG_*) - ored bitwise. Currently the following driver flags exist: -

+ information to the runtime system. If + field extended_marker equals ERL_DRV_EXTENDED_MARKER, + it is to contain 0 or driver flags (ERL_DRV_FLAG_*) + OR'ed bitwise. The following driver flags exist:

ERL_DRV_FLAG_USE_PORT_LOCKING - The runtime system will use port level locking on - all ports executing this driver instead of driver - level locking when the driver is run in a runtime - system with SMP support. For more information see the - erl_driver - documentation. - +

The runtime system uses port-level locking on + all ports executing this driver instead of driver-level + locking when the driver is run in a runtime + system with SMP support. For more information, see + + erl_driver.

+
ERL_DRV_FLAG_SOFT_BUSY - Marks that driver instances can handle being called - in the output and/or - outputv callbacks even - though a driver instance has marked itself as busy (see - set_busy_port()). - Since erts version 5.7.4 this flag is required for drivers used - by the Erlang distribution (the behaviour has always been - required by drivers used by the distribution). +

Marks that driver instances can handle being called + in the output and/or + outputv callbacks + although a driver instance has marked itself as busy (see + + erl_driver:set_busy_port). + As from ERTS 5.7.4 this flag is required for drivers used + by the Erlang distribution (the behavior has always been + required by drivers used by the distribution).

ERL_DRV_FLAG_NO_BUSY_MSGQ - Disable busy port message queue functionality. For - more information, see the documentation of the - erl_drv_busy_msgq_limits() - function. + +

Disables busy port message queue functionality. For + more information, see + + erl_driver:erl_drv_busy_msgq_limits.

ERL_DRV_FLAG_USE_INIT_ACK - When this flag is given the linked-in driver has to manually - acknowledge that the port has been successfully started using - erl_drv_init_ack(). - This allows the implementor to make the erlang:open_port exit with - badarg after some initial asynchronous initialization has been done. + +

When this flag is specified, the linked-in driver must manually + acknowledge that the port has been successfully started using + + erl_driver:erl_drv_init_ack(). + This allows the implementor to make the + erlang:open_port exit with badarg after some + initial asynchronous initialization has been done.

- void *handle2 + void *handle2 -

- This field is reserved for the emulator's internal use. The - emulator will modify this field; therefore, it is important - that the driver_entry isn't declared const. -

+

This field is reserved for the emulator's internal use. The + emulator modifies this field, so it is important + that the driver_entry is not declared const.

- void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor) + + void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor) + -

This callback is called when a monitored process exits. The +

Called when a monitored process exits. The drv_data is the data associated with the port for which - the process is monitored (using driver_monitor_process) - and the monitor corresponds to the ErlDrvMonitor + the process is monitored (using + + erl_driver:driver_monitor_process) + and the monitor corresponds to the ErlDrvMonitor structure filled in when creating the monitor. The driver interface function - driver_get_monitored_process - can be used to retrieve the process id of the exiting process as + + erl_driver:driver_get_monitored_process + can be used to retrieve the process ID of the exiting process as an ErlDrvTermData.

- void (*stop_select)(ErlDrvEvent event, void* reserved) + + void (*stop_select)(ErlDrvEvent event, void* reserved) -

This function is called on behalf of - driver_select - when it is safe to close an event object.

+

Called on behalf of + + erl_driver:driver_select + when it is safe to close an event object.

A typical implementation on Unix is to do - close((int)event).

-

Argument reserved is intended for future use and should be ignored.

-

In contrast to most of the other call-back functions, - stop_select is called independent of any port. No - ErlDrvData argument is passed to the function. No - driver lock or port lock is guaranteed to be held. The port that - called driver_select might even be closed at the - time stop_select is called. But it could also be - the case that stop_select is called directly by - driver_select.

+ close((int)event).

+

Argument reserved is intended for future use and is to be + ignored.

+

In contrast to most of the other callback functions, + stop_select is called independent of any port. No + ErlDrvData argument is passed to the function. No + driver lock or port lock is guaranteed to be held. The port that + called driver_select can even be closed at the + time stop_select is called. But it can also be + the case that stop_select is called directly by + erl_driver:driver_select.

It is not allowed to call any functions in the - driver API from - stop_select. This strict limitation is due to the - volatile context that stop_select may be called.

+ driver API from + stop_select. This strict limitation is because the + volatile context that stop_select can be called.

- - - -
- SEE ALSO -

erl_driver(3), - erl_ddll(3), - erlang(3), - kernel(3)

+ See Also +

erl_driver(3), + erlang(3), + kernel:erl_ddll(3)

-- cgit v1.2.3 From ad6e765bcd4f35a282ef00e38ed9129f3a5c1d83 Mon Sep 17 00:00:00 2001 From: Hans Bolinder Date: Thu, 1 Sep 2016 14:32:27 +0200 Subject: doc: Correct errors introduced by Editorial changes Fix some older errors as well. --- erts/doc/src/driver_entry.xml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'erts/doc/src/driver_entry.xml') diff --git a/erts/doc/src/driver_entry.xml b/erts/doc/src/driver_entry.xml index dea003f091..2421e0a8d9 100644 --- a/erts/doc/src/driver_entry.xml +++ b/erts/doc/src/driver_entry.xml @@ -4,7 +4,7 @@
- 20012015 + 20012016 Ericsson AB. All Rights Reserved. @@ -67,7 +67,7 @@ -

As from ERTS 5.9 (Erlang/OTP R15B) the driver interface +

As from ERTS 5.9 (Erlang/OTP R15B) the driver interface has been changed with larger types for the callbacks output, control, and @@ -78,7 +78,7 @@

Old drivers (compiled with an erl_driver.h from an - ERTS version earlier than 5.9) must be updated and have + ERTS version earlier than 5.9) must be updated and have to use the extended interface (with version management ).

@@ -481,7 +481,7 @@ typedef struct erl_drv_entry { although a driver instance has marked itself as busy (see erl_driver:set_busy_port). - As from ERTS 5.7.4 this flag is required for drivers used + As from ERTS 5.7.4 this flag is required for drivers used by the Erlang distribution (the behavior has always been required by drivers used by the distribution).

@@ -558,7 +558,7 @@ typedef struct erl_drv_entry { See Also

erl_driver(3), erlang(3), - kernel:erl_ddll(3)

+ erl_ddll(3)

-- cgit v1.2.3