Provided by: erlang-manpages_18.3-dfsg-1ubuntu3.1_all bug

NAME

       driver_entry - The driver-entry structure used by erlang drivers.

DESCRIPTION

   Warning:
       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.

       As of erts version 5.9 (OTP release R15B) the driver interface has been changed with larger types for the
       callbacks output, control and call. See driver  version management in erl_driver.

   Note:
       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 ).

       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.

       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 not to the other functions. The start
       function returns a driver-defined handle that is passed to the other functions. A 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 responsive.

       The driver structure contains the name of the driver and some 15 function pointers.  These  pointers  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);.

       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.

   Note:
       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.

DATA TYPES

         ErlDrvEntry:

         typedef struct erl_drv_entry {
             int (*init)(void);          /* called at system start up for statically
                                            linked drivers, and after loading for
                                            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. */
         #else
             ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts);
                                         /* special options, only for system driver */
         #endif
             void (*stop)(ErlDrvData drv_data);
                                         /* 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
                                            the port */
             void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
                                         /* 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
                                            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 */
             ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
                                     char *buf, ErlDrvSizeT len,
                            char **rbuf, ErlDrvSizeT rlen);
                                         /* "ioctl" for drivers - invoked by
                                            port_control/3 */
             void (*timeout)(ErlDrvData drv_data);        /* Handling of timeout in driver */
             void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev);
                                         /* 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
                                            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. */
             void (*event)(ErlDrvData drv_data, ErlDrvEvent event,
                           ErlDrvEventData event_data);
                                         /* 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 (*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;

           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.

           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.

           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  port.  If  drv_data  is  a  pointer  to  memory
             allocated in start, then stop is the place to deallocate that memory.

           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.

           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  something  that  the select system call
             understands).

             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.)

             On Enea OSE the event is one or more signals that can be retrieved using erl_drv_ose_get_signal.

             To use this with threads and asynchronous routines, create a pipe on unix, an Event on Windows or a
             unique signal number on Enea OSE. When the routine completes, write to the pipe  (use  SetEvent  on
             Windows  or  send  a message to the emulator process on Enea OSE), this will make 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 must
             nevertheless be able to handle such cases.

           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 library file (without the extension).

           void (*finish)(void):
             This  function  is 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.

           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.

           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 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 is too slow.

             If the driver wants to return data, it should 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 the port control flags (those that are set with 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. 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.

             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.

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

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

           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.

           void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev):
             This  function  is  called  whenever  the port is written to. If it is NULL, the output function is
             called instead. This function is faster than output, because 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, 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 variable, the reference
             counter can be incremented.

           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 opposed to the
             asynchronous function, which is called in some thread (if multithreading is enabled).

           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 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).

             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   term   and   returned   by
             erlang:port_call/3 to the 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.

             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.

           void (*event)(ErlDrvData drv_data, ErlDrvEvent event, ErlDrvEventData event_data):
             Intentionally left undocumented.

           int extended_marker:
             This field should either 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.

           int major_version:
             This  field  should  equal  ERL_DRV_EXTENDED_MAJOR_VERSION  if  the  extended_marker  field  equals
             ERL_DRV_EXTENDED_MARKER.

           int minor_version:
             This  field  should  equal  ERL_DRV_EXTENDED_MINOR_VERSION  if  the  extended_marker  field  equals
             ERL_DRV_EXTENDED_MARKER.

           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:

             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.

             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).

             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.

           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.

           void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor):
             This  callback  is  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  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 an ErlDrvTermData.

           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.

             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.

             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.

SEE ALSO

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

Ericsson AB                                         erts 7.3                                  driver_entry(3erl)