Provided by: erlang-manpages_14.b.4-dfsg-1ubuntu1_all bug


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


       As of erts version 5.5.3 the driver interface has been extended (see extended marker). The
       extended interface introduces version management, the possibility to pass capability flags
       (see driver flags) to the runtime system at driver initialization, and some new driver API

       Old drivers (compiled with an erl_driver.h from an earlier erts version than  5.5.3)  have
       to be recompiled (but do not have to use the extended interface).

       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"

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

       Do  not declare the driver_entryconst. 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.


         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. */
             ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts);
                                         /* special options, only for system driver */
             void (*stop)(ErlDrvData drv_data);
                                         /* called when port is closed, and when the
                                            emulator is halted. */
             void (*output)(ErlDrvData drv_data, char *buf, int 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 */
             int (*control)(ErlDrvData drv_data, unsigned int command, char *buf,
                            int len, char **rbuf, int 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 */
             int (*call)(ErlDrvData drv_data, unsigned int command, char *buf,
                            int len, char **rbuf, int 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 erl_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

           void (*output)(ErlDrvData drv_data, char *buf, int 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.)

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

           int  (*control)(ErlDrvData  drv_data,  unsigned  int command, char *buf, int len, char
           **rbuf, int 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).

           int  (*call)(ErlDrvData  drv_data,  unsigned  int  command,  char  *buf, int len, char
           **rbuf, int 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

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

                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.

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

           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

             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.


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