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)