driver_entry(3)



driver_entry(3erl)            C Library Functions           driver_entry(3erl)

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  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  miscel-
           laneous  misbehaviors  of the VM at any point after the call to the
           driver callback.

         * A driver callback doing lengthy work before returning degrades  re-
           sponsiveness  of the VM, and can cause miscellaneous strange behav-
           iors. Such strange behaviors include, but are not limited  to,  ex-
           treme  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  from  ERTS  5.9  (Erlang/OTP  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 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 de-
       fine. 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 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 func-
       tion returns a driver-defined handle that is passed to the other  func-
       tions.  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 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 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 func-
       tion returns the driver_entry structure that points to the other  func-
       tions in the driver. The 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  through  --enable-static-
       drivers,  you  must  define STATIC_ERLANG_DRIVER before the DRIVER_INIT
       declaration.

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

       typedef struct erl_drv_entry {
           int (*init)(void);          /* Called at system startup 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
                                          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
                                          port_control/3 */
           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
                                          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 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 */
           void* unused_event_callback;
           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):
           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):
           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):
           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.

         void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len):
           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_com-
           mand/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):
           Called when a driver event (specified in parameter event)  is  sig-
           naled.  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 function understands). (Some  trick-
           ery  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 completes, write
           to the pipe (use SetEvent on Windows), this makes the emulator call
           ready_input or ready_output.

           False events can occur. That is, calls to ready_input or ready_out-
           put 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:
           The driver name. It  must  correspond  to  the  atom  used  in  er-
           lang:open_port/2,  and the name of the driver library file (without
           the extension).

         void (*finish)(void):
           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 erl_ddll:un-
           load_driver/1, or when the emulator halts.

         void *handle:
           This field is reserved for the emulator's internal use. The  emula-
           tor  will modify this field, so it is important that the driver_en-
           try is not declared const.

         ErlDrvSSizeT (*control)(ErlDrvData drv_data,  unsigned  int  command,
         char *buf, ErlDrvSizeT len, char **rbuf, ErlDrvSizeT rlen):
           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
           makes no context switch in the Erlang emulator and requires no mes-
           sage 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 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 differ-
           ently depending on the port control flags (those that are set  with
           erl_driver:set_port_control_flags).

           If  the  flag  is  set to PORT_CONTROL_FLAG_BINARY, a binary is re-
           turned. 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
           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 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.

         void (*timeout)(ErlDrvData drv_data):
           Called  any  time  after the driver's timer reaches 0. The timer is
           activated with erl_driver:driver_set_timer. No priorities or order-
           ing 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):
           Called whenever the port is written to. If it is NULL,  the  output
           function is called instead. This function is faster than output, as
           it takes an ErlIOVec directly, which requires  no  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 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):
           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 asynchro-
           nous  function,  which is called in 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):
           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 sec-
           ond 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 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 return data,
           *rbuf can be set to memory allocated with  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),  er-
           lang:port_call/3 throws a BAD_ARG.

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

         int 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) 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:
           This  field is to equal ERL_DRV_EXTENDED_MAJOR_VERSION if field ex-
           tended_marker equals ERL_DRV_EXTENDED_MARKER.

         int minor_version:
           This field is to equal ERL_DRV_EXTENDED_MINOR_VERSION if field  ex-
           tended_marker equals ERL_DRV_EXTENDED_MARKER.

         int driver_flags:
           This  field is used to pass driver capability and other information
           to the runtime system. If field extended_marker equals  ERL_DRV_EX-
           TENDED_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 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 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:
             Disables busy port message queue functionality. For more informa-
             tion, see erl_driver:erl_drv_busy_msgq_limits.

           ERL_DRV_FLAG_USE_INIT_ACK:
             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:
           This  field is reserved for the emulator's internal use. The emula-
           tor modifies this field, so it is important that  the  driver_entry
           is not declared const.

         void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor):
           Called when a monitored process exits. The drv_data is the data as-
           sociated with the port for which 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   erl_driver:driver_get_moni-
           tored_process can be used to retrieve the process ID of the exiting
           process as an ErlDrvTermData.

         void (*stop_select)(ErlDrvEvent event, void* reserved):
           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 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 because the volatile context
           that stop_select can be called.

SEE ALSO
       erl_driver(3erl), erlang(3erl), erl_ddll(3erl)

Ericsson AB                       erts 11.0.2               driver_entry(3erl)

Man(1) output converted with man2html
list of all man pages