An Erlang driver is a library containing a set of native driver callback functions that the Erlang VM calls when certain events occur. There may be multiple instances of a driver, each instance is associated with an Erlang port.
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 
As of erts version 5.5.3 the driver interface has been extended
      (see 
As of erts version 5.9 old drivers have to be recompiled
      and have to use the extended interface. They also have to be
      adjusted to the
      
The driver calls back to the emulator, using the API
      functions declared in 
Each driver instance is associated with a port. Every port
      has a port owner process. Communication with the port is normally
      done through the port owner process. Most of the functions take
      the 
Some of the functions take a parameter of type
      
Many of the output functions have a "header buffer", with
      
In the runtime system with SMP support, drivers are locked either
      on driver level or port level (driver instance level). By default
      driver level locking will be used, i.e., only one emulator thread
      will execute code in the driver at a time. If port level locking
      is used, multiple emulator threads may execute code in the driver
      at the same time. There will only be one thread at a time calling
      driver call-backs corresponding to the same port, though. In order
      to enable port level locking set the 
Most drivers written before the runtime system with SMP support existed will be able to run in the runtime system with SMP support without being rewritten if driver level locking is used.
It is assumed that drivers do not access other drivers. If drivers should access each other they have to provide their own mechanism for thread safe synchronization. Such "inter driver communication" is strongly discouraged.
Previously, in the runtime system without SMP support, specific driver call-backs were always called from the same thread. This is not the case in the runtime system with SMP support. Regardless of locking scheme used, calls to driver call-backs may be made from different threads, e.g., two consecutive calls to exactly the same call-back for exactly the same port may be made from two different threads. This will for most drivers not be a problem, but it might. Drivers that depend on all call-backs being called in the same thread, have to be rewritten before being used in the runtime system with SMP support.
Regardless of locking scheme used, calls to driver call-backs may be made from different threads.
Most functions in this API are not thread-safe, i.e., they may not be called from an arbitrary thread. Functions that are not documented as thread-safe may only be called from driver call-backs or function calls descending from a driver call-back call. Note that driver call-backs may be called from different threads. This, however, is not a problem for any function in this API, since the emulator has control over these threads.
Functions not explicitly documented as thread safe are not thread safe. Also note that some functions are only thread safe when used in a runtime system with SMP support.
A function not explicitly documented as thread safe may at some point in time have a thread safe implementation in the runtime system. Such an implementation may however change to a thread unsafe implementation at any time without any notice at all.
Only use functions explicitly documented as thread safe from arbitrary threads.
All functions that a driver needs to do with Erlang are performed through driver API functions. There are functions for the following functionality:
Every driver instance has an associated queue. This queue is a
          
The queue can be manipulated from arbitrary threads if
          a port data lock is used. See documentation of the
          
A POSIX thread like API for multi-threading is provided. The Erlang driver thread API only provide a subset of the functionality provided by the POSIX thread API. The subset provided is more or less the basic functionality needed for multi-threaded programming:
The Erlang driver thread API can be used in conjunction with the POSIX thread API on UN-ices and with the Windows native thread API on Windows. The Erlang driver thread API has the advantage of being portable, but there might exist situations where you want to use functionality from the POSIX thread API or the Windows native thread API.
The Erlang driver thread API only returns error codes when it is reasonable to recover from an error condition. If it isn't reasonable to recover from an error condition, the whole runtime system is terminated. For example, if a create mutex operation fails, an error code is returned, but if a lock operation on a mutex fails, the whole runtime system is terminated.
Note that there exists no "condition variable wait with timeout" in
         the Erlang driver thread API. This is due to issues with
	 
In order for the Erlang driver thread API to function, thread
         support has to be enabled in the runtime system. An Erlang driver
	 can check if thread support is enabled by use of
	 
NOTE: When executing in an emulator thread, it is very important that you unlock all locks you have locked before letting the thread out of your control; otherwise, you are very likely to deadlock the whole emulator. If you need to use thread specific data in an emulator thread, only have the thread specific data set while the thread is under your control, and clear the thread specific data before you let the thread out of your control.
In the future there will probably be debug functionality
         integrated with the Erlang driver thread API. All functions
	 that create entities take a 
A driver can add and later remove drivers.
A driver can monitor a process that does not own a port.
Version management is enabled for drivers that have set the
          
The emulator will refuse to load a driver that does not use
	  the extended driver interface,
	  to allow for 64-bit capable drivers,
	  since incompatible type changes for the callbacks
	  
Therefore it is not enough to just recompile drivers written with version management for pre-R15B types; the types have to be changed in the driver suggesting other rewrites especially regarding size variables. Investigate all warnings when recompiling!
Also, the API driver functions 
      For erts-5.9 two new integer types
      
To not update a driver and just recompile it probably works when building for a 32-bit machine creating a false sense of security. Hopefully that will generate many important warnings. But when recompiling the same driver later on for a 64-bit machine there will be warnings and almost certainly crashes. So it is a BAD idea to postpone updating the driver and not fixing the warnings!
      When recompiling with 
Here follows a checklist for rewriting a pre erts-5.9 driver, most important first.
	  Rewrite driver callback
	  
	  Rewrite driver callback
	  
These changes are essential to not crash the emulator or worse cause malfunction. Without them a driver may return garbage in the high 32 bits to the emulator causing it to build a huge result from random bytes either crashing on memory allocation or succeeding with a random result from the driver call.
	  Driver callback
	  
	  Driver callback
	  
	  Driver callback
	  
	  Sane compiler's calling conventions probably make these changes
	  necessary only for a driver to handle data chunks that require
	  64-bit size fields (mostly larger than 2 GB since that is what
	  an 
The argument type change is from signed to unsigned which may cause problems for e.g. loop termination conditions or error conditions if you just change the types all over the place.
	  The 
Automatic type casting probably makes these changes necessary only for a driver that encounters sizes larger than 32 bits.
	    The 
	  Many driver API functions have changed argument type
	  and/or return value to 
This is a change from signed to unsigned which may cause problems for e.g. loop termination conditions and error conditions if you just change the types all over the place.
An unsigned integer type to be used as 
A signed integer type the size of 
typedef struct ErlDrvSysInfo {
   int driver_major_version;
   int driver_minor_version;
   char *erts_version;
   char *otp_release;
   int thread_support;
   int smp_support;
   int async_threads;
   int scheduler_threads;
   int nif_major_version;
   int nif_minor_version;
   int dirty_scheduler_support;
} ErlDrvSysInfo;
      
      
        The 
typedef struct ErlDrvBinary {
   ErlDrvSint orig_size;
   char orig_bytes[];
} ErlDrvBinary;
        The 
The 
Some driver calls, such as 
Using a driver binary instead of a normal buffer, is often faster, since the emulator doesn't need to copy the data, only the pointer is used.
A driver binary allocated in the driver, with
          
Driver binaries are used in the 
If the driver for some reason or another, wants to keep a
          driver binary around, in a static variable for instance, the
          reference count should be incremented,
          and the binary can later be freed in the 
Note that since a driver binary is shared by the driver and the emulator, a binary received from the emulator or sent to the emulator, must not be changed by the driver.
Since erts version 5.5 (OTP release R11B), orig_bytes is guaranteed to be properly aligned for storage of an array of doubles (usually 8-byte aligned).
The 
This is a system I/O vector, as used by 
typedef struct ErlIOVec {
  int vsize;
  ErlDrvSizeT size;
  SysIOVec* iov;
  ErlDrvBinary** binv;
} ErlIOVec;
        The I/O vector used by the emulator and drivers, is a list
          of binaries, with a 
When a driver creates a monitor for a process, a
          
The driver writer should provide the memory for storing the
          monitor when calling 
The 
If certain port specific data have to be accessed from other threads than those calling the driver call-backs, a port data lock can be used in order to synchronize the operations on the data. Currently, the only port specific data that the emulator associates with the port data lock is the driver queue.
Normally a driver instance does not have a port data lock. If
          the driver instance wants to use a port data lock, it has to
          create the port data lock by calling
          
A port data lock is reference counted, and when the reference
          count reaches zero, it will be destroyed. The emulator will at
          least increment the reference count once when the lock is
          created and decrement it once when the port associated with
          the lock terminates. The emulator will also increment the
          reference count when an async job is enqueued and decrement
          it after an async job has been invoked. Besides
          this, it is the responsibility of the driver to ensure that
          the reference count does not reach zero before the last use
          of the lock by the driver has been made. The reference count
          can be read, incremented, and decremented, respectively, by
          use of
          
Thread identifier.
See also:
	   
	int suggested_stack_size;
      
        Thread options structure passed to
	   
See also:
	   
Mutual exclusion lock. Used for synchronizing access to shared data. Only one thread at a time can lock a mutex.
See also:
	   
Condition variable. Used when threads need to wait for a specific condition to appear before continuing execution. Condition variables need to be used with associated mutexes.
See also:
	   
Read/write lock. Used to allow multiple threads to read shared data while only allowing one thread to write the same data. Multiple threads can read lock an rwlock at the same time, while only one thread can read/write lock an rwlock at a time.
See also:
	   
Key which thread specific data can be associated with.
See also:
	   
This function will write information about the Erlang runtime
          system into the
          
See the documentation of the
          
The 
The data is queued in the port owner process' message queue. Note that this does not yield to the emulator. (Since the driver and the emulator run in the same thread.)
The parameter 
The return value for all output functions is 0. (Unless the driver is used for distribution, in which case it can fail and return -1. For normal use, the output function always returns 0.)
The 
The point of sending data as a list header, is to facilitate matching on the data received.
The return value is 0 for normal use.
This function sends data to port owner process from a
          driver binary, it has a header buffer (
The parameter 
Driver binaries are created with 
The data in the header is sent as a list and the binary as an Erlang binary in the tail of the list.
E.g. if 
The return value is 0 for normal use.
Note that, using the binary syntax in Erlang, the driver application can match the header directly from the binary, so the header can be put in the binary, and hlen can be set to 0.
This function sends data from an IO vector, 
The 
You get vectors of 
E.g. if 
The return value is 0 for normal use.
The comment for 
This function collects several segments of data, referenced
          by 
If the data is to be sent from the driver to the port owner
          process, it is faster to use 
The return value is the space left in the buffer, i.e. if
          the 
This function sets a timer on the driver, which will count
          down and call the driver when it is timed out. The
          
When the timer reaches 0 and expires, the driver entry
          function 
Note that there is only one timer on each driver instance; setting a new timer will replace an older one.
Return value is 0 (-1 only when the 
This function cancels a timer set with
          
The return value is 0.
This function reads the current time of a timer, and places
          the result in 
The return value is 0.
This function reads a timestamp into the memory pointed to by
          the parameter 
The return value is 0 unless the 
This function is used by drivers to provide the emulator with events to check for. This enables the emulator to call the driver when something has happened asynchronously.
The 
The 
The 
Some OS (Windows and Enea OSE) do not differentiate between read and write events.
         The call-back for a fired event then only depends on the value of 
ERL_DRV_USE was added in OTP release R13. Old drivers will still work
         as before. But it is recommended to update them to use 
The return value is 0 (failure, -1, only if the
          
This function allocates a memory block of the size specified
          in 
Memory allocated must be explicitly freed with a corresponding
           call to 
This function is thread-safe.
This function resizes a memory block, either in place, or by
          allocating a new block, copying the data and freeing the old
          block. A pointer is returned to the reallocated memory. On
          failure (out of memory), 
This function is thread-safe.
This function frees the memory pointed to by 
This function is thread-safe.
This function allocates a driver binary with a memory block
          of at least 
Note that a driver binary has an internal reference counter,
          this means that calling 
The driver binary has a field, 
This function is thread-safe.
This function resizes a driver binary, while keeping the
          data. The resized driver binary is returned. On failure (out
          of memory), 
This function is only thread-safe when the emulator with SMP support is used.
This function frees a driver binary 
This function is only thread-safe when the emulator with SMP support is used.
Returns current reference count on 
This function is only thread-safe when the emulator with SMP support is used.
Increments the reference count on 
This function is only thread-safe when the emulator with SMP support is used.
Decrements the reference count on 
This function is only thread-safe when the emulator with SMP support is used.
You should normally decrement the reference count of a
            driver binary by calling
            
This function enqueues data in the driver queue. The data in
          
The driver queue is available to queue output from the emulator to the driver (data from the driver to the emulator is queued by the emulator in normal erlang message queues). This can be useful if the driver has to wait for slow devices etc, and wants to yield back to the emulator. The driver queue is implemented as an ErlIOVec.
When the queue contains data, the driver won't close, until the queue is empty.
The return value is 0.
This function can be called from an arbitrary thread if a
          
This function puts data at the head of the driver queue. The
          data in 
The return value is 0.
This function can be called from an arbitrary thread if a
          
This function dequeues data by moving the head pointer
          forward in the driver queue by 
The return value is the number of bytes remaining in the queue or -1 on failure.
This function can be called from an arbitrary thread if a
          
This function returns the number of bytes currently in the driver queue.
This function can be called from an arbitrary thread if a
          
This function enqueues a driver binary in the driver
          queue. The data in 
This function can be called from an arbitrary thread if a
          
The return value is 0.
This function puts data in the binary 
This function can be called from an arbitrary thread if a
          
The return value is 0.
	  This function retrieves the driver queue into a supplied
	  
	  If 
Nothing is removed from the queue by this function, that must be done
          with 
This function can be called from an arbitrary thread if a
          
This function retrieves the driver queue as a pointer to an
          array of 
Nothing is removed from the queue by this function, that must be done
          with 
The returned array is suitable to use with the Unix system
          call 
This function can be called from an arbitrary thread if a
          
This function enqueues the data in 
The return value is 0.
This function can be called from an arbitrary thread if a
          
This function puts the data in 
The return value is 0.
This function can be called from an arbitrary thread if a
          
This function creates a port data lock associated with
          the 
On success a newly created port data lock is returned. On
          failure 
This function locks the port data lock passed as argument
          (
This function is thread-safe.
This function unlocks the port data lock passed as argument
          (
This function is thread-safe.
This function returns the current reference count of
          the port data lock passed as argument (
This function is thread-safe.
This function increments the reference count of
          the port data lock passed as argument (
The current reference count after the increment has been performed is returned.
This function is thread-safe.
This function decrements the reference count of
          the port data lock passed as argument (
The current reference count after the decrement has been performed is returned.
This function is thread-safe.
Start monitoring a process from a driver. When a process is
          monitored, a process exit will result in a call to the
          provided 
The 
The function returns 0 on success, < 0 if no call-back is provided and > 0 if the process is no longer alive.
This function cancels a monitor created earlier.
The function returns 0 if a monitor was removed and > 0 if the monitor did no longer exist.
The function returns the process id associated with a living
          monitor. It can be used in the 
The function returns 
This function is used to compare two 
The function returns 0 if 
This function adds a driver entry to the list of drivers
          known by Erlang. The 
To use this function for adding drivers residing in
            dynamically loaded code is dangerous. If the driver code
            for the added driver resides in the same dynamically
            loaded module (i.e. 
Use of this function is generally deprecated.
This function removes a driver entry 
Driver entries added by the 
This function returns the atom name of the erlang error,
          given the error number in 
Sets and gets limits that will be used for controling the busy state of the port message queue.
The port message queue will be set into a busy
	state when the amount of command data queued on the
	message	queue reaches the 
Valid limits are values in the range
	
By passing a pointer to an integer variable containing
	the value 
The busy message queue feature can be disabled either
	by setting the 
Processes sending command data to the port will be suspended if either the port is busy or if the port message queue is busy. Suspended processes will be resumed when neither the port is busy, nor the port message queue is busy.
For information about busy port functionality
	see the documentation of the
	
This function set and unset the busy state of the port. If
          
Processes sending command data to the port will be suspended
	if either the port is busy or if the port message queue
	is busy. Suspended processes will be resumed when neither the
	port is busy, nor the port message queue is busy. Command data
	is in this context data passed to the port using either
	
If the
	   
For information about busy port message queue functionality
	see the documentation of the
	
This function sets flags for how the 
Currently there are only two meaningful values for
          
This function signals to erlang that the driver has
          encountered an EOF and should be closed, unless the port was
          opened with the 
The return value is 0.
These functions signal to Erlang that the driver has
          encountered an error and should be closed. The port is
          closed and the tuple 
The driver should fail only when in severe error situations,
          when the driver cannot possibly keep open, for instance
          buffer allocation gets out of memory. For normal errors
          it is more appropriate to send error codes with
          
The return value is 0.
This function returns the port owner process.
Note that this function is not thread-safe, not even when the emulator with SMP support is used.
This function returns the process id of the process that
	  made the current call to the driver. The process id can be
	  used with 
Note that this function is not thread-safe, not even when the emulator with SMP support is used.
This functions sends data in the special driver term
          format to the port owner process. This is a fast way to
	  deliver term data from a driver. It also needs no binary
	  conversion, so the port owner process receives data as
	  normal Erlang terms. The
	  
Note that the 
The 
Tuples, maps and lists (with the exception of strings, see below), are built in reverse polish notation, so that to build a tuple, the elements are given first, and then the tuple term, with a count. Likewise for lists and maps.
A tuple must be specified with the number of elements. (The
          elements precede the 
A list must be specified with the number of elements,
          including the tail, which is the last term preceding
          
A map must be specified with the number of key-value pairs 
The special term 
Term type            Argument(s)
===========================================
ERL_DRV_NIL
ERL_DRV_ATOM         ErlDrvTermData atom (from driver_mk_atom(char *string))
ERL_DRV_INT          ErlDrvSInt integer
ERL_DRV_UINT         ErlDrvUInt integer
ERL_DRV_INT64        ErlDrvSInt64 *integer_ptr
ERL_DRV_UINT64       ErlDrvUInt64 *integer_ptr
ERL_DRV_PORT         ErlDrvTermData port (from driver_mk_port(ErlDrvPort port))
ERL_DRV_BINARY       ErlDrvBinary *bin, ErlDrvUInt len, ErlDrvUInt offset
ERL_DRV_BUF2BINARY   char *buf, ErlDrvUInt len
ERL_DRV_STRING       char *str, int len
ERL_DRV_TUPLE        int sz
ERL_DRV_LIST         int sz
ERL_DRV_PID          ErlDrvTermData pid (from driver_connected(ErlDrvPort port) or driver_caller(ErlDrvPort port))
ERL_DRV_STRING_CONS  char *str, int len
ERL_DRV_FLOAT        double *dbl
ERL_DRV_EXT2TERM     char *buf, ErlDrvUInt len
ERL_DRV_MAP          int sz
        
	The unsigned integer data type 
The unsigned integer data type 
To build the tuple 
      
        Where 
The term 
The 
        
        
	The 
orig_bytes, binp->orig_size
        ERL_DRV_TUPLE, 2,
    };
    erl_drv_output_term(driver_mk_port(drvport), spec, sizeof(spec) / sizeof(spec[0]));
        ]]>
        To build the map 
      
	If you want to pass a binary and don't already have the content
	of the binary in an 
The 
This function is only thread-safe when the emulator with SMP support is used.
The parameters 
Note that this function is not thread-safe, not even when the emulator with SMP support is used.
This function returns an atom given a name
          
Note that this function is not thread-safe, not even when the emulator with SMP support is used.
This function converts a port handle to the erlang term
          format, usable in the 
Note that this function is not thread-safe, not even when the emulator with SMP support is used.
This function is the only way for a driver to send data to
          other processes than the port owner process. The
          
Note that the 
The parameters 
This function is only thread-safe when the emulator with SMP support is used.
Also note that parameters of 
The parameters 
This function is only thread-safe when the emulator with SMP support is used.
This function performs an asynchronous call. The function
          
The async thread pool size can be set with the
          
If there is a thread pool available, a thread will be
          used. If the 
To make sure that a driver instance always uses the same thread, the following call can be used:
        It is enough to initialize 
If a thread is already working, the calls will be queued up and executed in order. Using the same thread for each driver instance ensures that the calls will be made in sequence.
The 
When the async operation is done, 
The return value is -1 if the 
As of erts version 5.5.4.3 the default stack size for
            threads in the async-thread pool is 16 kilowords,
            i.e., 64 kilobyte on 32-bit architectures.
            This small default size has been chosen since the
            amount of async-threads might be quite large. The
            default stack size is enough for drivers delivered
            with Erlang/OTP, but might not be sufficiently large
            for other dynamically linked in drivers that use the
            driver_async() functionality. A suggested stack size
            for threads in the async-thread pool can be configured
            via the
            
This function calculates a key for later use in 
Before OTP-R16, the actual port id could be used as a key with proper casting, but after the rewrite of the port subsystem, this is no longer the case. With this function, you can achieve the same distribution based on port id's as before OTP-R16.
This function locks the driver used by the port 
This function creates a new port executing the same driver code as the port creating the new port. A short description of the arguments:
The caller of 
When
            
Arguments:
This function creates a new thread. On success 
You are not allowed to allocate the
	            
The created thread will terminate either when 
All created threads need to be joined by the driver before it is unloaded. If the driver fails to join all threads created before it is unloaded, the runtime system will most likely crash when the code of the driver is unloaded.
This function is thread-safe.
Arguments:
This function allocates and initialize a thread option
	   structure. On failure 
You are not allowed to allocate the
	            
This function is thread-safe.
Arguments:
This function destroys thread options previously created by
	   
This function is thread-safe.
Arguments:
This function terminates the calling thread with the exit
	   value passed as argument. You are only allowed to terminate
	   threads created with
	   
This function is thread-safe.
Arguments:
This function joins the calling thread with another thread, i.e.,
	   the calling thread is blocked until the thread identified by
	   
This function is thread-safe.
This function returns the thread identifier of the calling thread.
This function is thread-safe.
Arguments:
This function compares two thread identifiers for equality,
	   and returns 
A Thread identifier may be reused very quickly after
	         a thread has terminated. Therefore, if a thread
		 corresponding to one of the involved thread identifiers
		 has terminated since the thread identifier was saved,
		 the result of 
This function is thread-safe.
Arguments:
This function creates a mutex and returns a pointer to it. On
	   failure 
This function is thread-safe.
Arguments:
This function destroys a mutex previously created by
	   
This function is thread-safe.
Arguments:
This function locks a mutex. The calling thread will be blocked until the mutex has been locked. A thread which currently has locked the mutex may not lock the same mutex again.
If you leave a mutex locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function tries to lock a mutex. If successful 
If you leave a mutex locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function unlocks a mutex. The mutex currently has to be locked by the calling thread.
This function is thread-safe.
Arguments:
This function creates a condition variable and returns a
	   pointer to it. On failure 
This function is thread-safe.
Arguments:
This function destroys a condition variable previously
	   created by
	   
This function is thread-safe.
Arguments:
This function signals on a condition variable. That is, if other threads are waiting on the condition variable being signaled, one of them will be woken.
This function is thread-safe.
Arguments:
This function broadcasts on a condition variable. That is, if other threads are waiting on the condition variable being broadcast on, all of them will be woken.
This function is thread-safe.
Arguments:
This function waits on a condition variable. The calling thread is blocked until another thread wakes it by signaling or broadcasting on the condition variable. Before the calling thread is blocked it unlocks the mutex passed as argument, and when the calling thread is woken it locks the same mutex before returning. That is, the mutex currently has to be locked by the calling thread when calling this function.
This function is thread-safe.
Arguments:
This function creates an rwlock and returns a pointer to it. On
	   failure 
This function is thread-safe.
Arguments:
This function destroys an rwlock previously created by
	   
This function is thread-safe.
Arguments:
This function read locks an rwlock. The calling thread will be blocked until the rwlock has been read locked. A thread which currently has read or read/write locked the rwlock may not lock the same rwlock again.
If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function tries to read lock an rwlock. If successful
	   
If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function read unlocks an rwlock. The rwlock currently has to be read locked by the calling thread.
This function is thread-safe.
Arguments:
This function read/write locks an rwlock. The calling thread will be blocked until the rwlock has been read/write locked. A thread which currently has read or read/write locked the rwlock may not lock the same rwlock again.
If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function tries to read/write lock an rwlock. If successful
	   
If you leave an rwlock locked in an emulator thread when you let the thread out of your control, you will very likely deadlock the whole emulator.
This function is thread-safe.
Arguments:
This function read/write unlocks an rwlock. The rwlock currently has to be read/write locked by the calling thread.
This function is thread-safe.
Arguments:
This function creates a thread specific data key. On success
	   
This function is thread-safe.
Arguments:
This function destroys a thread specific data key
	   previously created by
	   
A destroyed key is very likely to be reused soon. Therefore, if you fail to clear the thread specific data using this key in a thread prior to destroying the key, you will very likely get unexpected errors in other parts of the system.
This function is thread-safe.
Arguments:
This function sets thread specific data associated with
	   
If you fail to clear thread specific data in an emulator thread before letting it out of your control, you might not ever be able to clear this data with later unexpected errors in other parts of the system as a result.
This function is thread-safe.
Arguments:
This function returns the thread specific data
	   associated with 
This function is thread-safe.
Arguments:
This function sets the value of an environment variable.
	   It returns 
The result of passing the empty string ("") as a value is platform dependent. On some platforms the value of the variable is set to the empty string, on others, the environment variable is removed.
Do not use libc's 
This function is thread-safe.
Arguments:
This function retrieves the value of an environment variable.
	When called, 
Do not use libc's 
This function is thread-safe.
Arguments:
Give the runtime system a hint about how much CPU time the
	current driver callback call has consumed since last hint, or
	since the start of the callback if no previous hint has been given.
	The time is given as a fraction, in percent, of a full time-slice
	that a port is allowed to execute before it should surrender the
	CPU to other runnable ports or processes. Valid range is
	
Note that it is up to the runtime system to determine if and
	how to	use this information. Implementations on some platforms
	may use other means in order to determine the consumed fraction
	of the time-slice. Lengthy driver callbacks should regardless of
	this frequently call the 
This function is provided to better support co-operative scheduling,
	improve system responsiveness, and to make it easier to prevent
	misbehaviors of the VM due to a port monopolizing a scheduler thread.
	It can be used when dividing length work into a number of repeated
	driver callback calls without the need to use threads. Also see the
	important 
Arguments:
Returns a pointer to the name of the condition.
This function is intended for debugging purposes only.
Arguments:
Returns a pointer to the name of the mutex.
This function is intended for debugging purposes only.
Arguments:
Returns a pointer to the name of the r/w-lock.
This function is intended for debugging purposes only.
Arguments:
Returns a pointer to the name of the thread.
This function is intended for debugging purposes only.
An Alternative Distribution Driver (ERTS User's Guide Ch. 3)