/*
* %CopyrightBegin%
*
* Copyright Ericsson AB 2009-2018. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* %CopyrightEnd%
*/
/* Include file for writers of Native Implemented Functions.
*/
#ifndef __ERL_NIF_H__
#define __ERL_NIF_H__
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "erl_drv_nif.h"
/* Version history:
** 0.1: R13B03
** 1.0: R13B04
** 2.0: R14A
** 2.1: R14B02 "vm_variant"
** 2.2: R14B03 enif_is_exception
** 2.3: R15 enif_make_reverse_list, enif_is_number
** 2.4: R16 enif_consume_timeslice
** 2.5: First experimental maps API additions (libs of this version is not compatible with any other VM)
** 2.5: R17 Maps API additions
** 2.6: R17 with maps
** R17 dirty schedulers
** 2.7: 17.3 add enif_schedule_nif
** remove enif_schedule_dirty_nif, enif_schedule_dirty_nif_finalizer, enif_dirty_nif_finalizer
** add ErlNifEntry options
** add ErlNifFunc flags
** 2.8: 18.0 add enif_has_pending_exception
** 2.9: 18.2 enif_getenv
** 2.10: Time API
** 2.11: 19.0 enif_snprintf
** 2.12: 20.0 add enif_select, enif_open_resource_type_x
** 2.13: 20.1 add enif_ioq
** 2.14: 21.0 add enif_ioq_peek_head, enif_(mutex|cond|rwlock|thread)_name
** enif_vfprintf, enif_vsnprintf, enif_make_map_from_arrays
** 2.15: 22.0 ERL_NIF_SELECT_CANCEL, enif_select_(read|write)
** enif_term_type
*/
#define ERL_NIF_MAJOR_VERSION 2
#define ERL_NIF_MINOR_VERSION 15
/*
* WHEN CHANGING INTERFACE VERSION, also replace erts version below with
* a ticket number e.g. "erts-@OTP-12345@". The syntax is the same as for
* runtime dependencies so multiple tickets should be separated with ":", e.g.
* "erts-@OTP-12345:OTP-54321@".
*
* If you're not on the OTP team, you should use a placeholder like
* erts-@MyName@ instead.
*/
#define ERL_NIF_MIN_ERTS_VERSION "erts-10.4"
/*
* The emulator will refuse to load a nif-lib with a major version
* lower than ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD. The load
* may however fail if user have not removed use of deprecated
* symbols.
*
* The ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD have to allow
* loading of nif-libs built at least two major OTP releases
* ago.
*/
#define ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD 2
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef ErlNapiUInt64 ErlNifUInt64;
typedef ErlNapiSInt64 ErlNifSInt64;
typedef ErlNapiUInt ErlNifUInt;
typedef ErlNapiSInt ErlNifSInt;
# define ERL_NIF_VM_VARIANT "beam.vanilla"
typedef ErlNifUInt ERL_NIF_TERM;
typedef ERL_NIF_TERM ERL_NIF_UINT;
typedef ErlNifSInt64 ErlNifTime;
#define ERL_NIF_TIME_ERROR ((ErlNifSInt64) ERTS_NAPI_TIME_ERROR__)
typedef enum {
ERL_NIF_SEC = ERTS_NAPI_SEC__,
ERL_NIF_MSEC = ERTS_NAPI_MSEC__,
ERL_NIF_USEC = ERTS_NAPI_USEC__,
ERL_NIF_NSEC = ERTS_NAPI_NSEC__
} ErlNifTimeUnit;
struct enif_environment_t;
typedef struct enif_environment_t ErlNifEnv;
typedef struct enif_func_t
{
const char* name;
unsigned arity;
ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
unsigned flags;
}ErlNifFunc;
typedef struct enif_entry_t
{
int major;
int minor;
const char* name;
int num_of_funcs;
ErlNifFunc* funcs;
int (*load) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info);
int (*reload) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info);
int (*upgrade)(ErlNifEnv*, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info);
void (*unload) (ErlNifEnv*, void* priv_data);
/* Added in 2.1 */
const char* vm_variant;
/* Added in 2.7 */
unsigned options; /* Unused. Can be set to 0 or 1 (dirty sched config) */
/* Added in 2.12 */
size_t sizeof_ErlNifResourceTypeInit;
/* Added in 2.14 */
const char* min_erts;
}ErlNifEntry;
typedef struct
{
size_t size;
unsigned char* data;
/* Internals (avert your eyes) */
void* ref_bin;
/* for future additions to be ABI compatible (same struct size) */
void* __spare__[2];
}ErlNifBinary;
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
typedef void* ErlNifEvent; /* FIXME: Use 'HANDLE' somehow without breaking existing source */
#else
typedef int ErlNifEvent;
#endif
/* Return bits from enif_select: */
#define ERL_NIF_SELECT_STOP_CALLED (1 << 0)
#define ERL_NIF_SELECT_STOP_SCHEDULED (1 << 1)
#define ERL_NIF_SELECT_INVALID_EVENT (1 << 2)
#define ERL_NIF_SELECT_FAILED (1 << 3)
#define ERL_NIF_SELECT_READ_CANCELLED (1 << 4)
#define ERL_NIF_SELECT_WRITE_CANCELLED (1 << 5)
typedef enum
{
ERL_NIF_RT_CREATE = 1,
ERL_NIF_RT_TAKEOVER = 2
}ErlNifResourceFlags;
typedef enum
{
ERL_NIF_LATIN1 = 1
}ErlNifCharEncoding;
typedef struct
{
ERL_NIF_TERM pid; /* internal, may change */
} ErlNifPid;
typedef struct
{
ERL_NIF_TERM port_id; /* internal, may change */
}ErlNifPort;
typedef ErlDrvMonitor ErlNifMonitor;
typedef struct enif_resource_type_t ErlNifResourceType;
typedef void ErlNifResourceDtor(ErlNifEnv*, void*);
typedef void ErlNifResourceStop(ErlNifEnv*, void*, ErlNifEvent, int is_direct_call);
typedef void ErlNifResourceDown(ErlNifEnv*, void*, ErlNifPid*, ErlNifMonitor*);
typedef struct {
ErlNifResourceDtor* dtor;
ErlNifResourceStop* stop; /* at ERL_NIF_SELECT_STOP event */
ErlNifResourceDown* down; /* enif_monitor_process */
} ErlNifResourceTypeInit;
typedef ErlDrvSysInfo ErlNifSysInfo;
typedef struct ErlDrvTid_ *ErlNifTid;
typedef struct ErlDrvMutex_ ErlNifMutex;
typedef struct ErlDrvCond_ ErlNifCond;
typedef struct ErlDrvRWLock_ ErlNifRWLock;
typedef int ErlNifTSDKey;
typedef ErlDrvThreadOpts ErlNifThreadOpts;
typedef enum
{
ERL_NIF_DIRTY_JOB_CPU_BOUND = ERL_DIRTY_JOB_CPU_BOUND,
ERL_NIF_DIRTY_JOB_IO_BOUND = ERL_DIRTY_JOB_IO_BOUND
}ErlNifDirtyTaskFlags;
typedef struct /* All fields all internal and may change */
{
ERL_NIF_TERM map;
ERL_NIF_UINT size;
ERL_NIF_UINT idx;
union {
struct {
ERL_NIF_TERM *ks;
ERL_NIF_TERM *vs;
}flat;
struct {
struct ErtsDynamicWStack_* wstack;
ERL_NIF_TERM* kv;
}hash;
}u;
void* __spare__[2]; /* for future additions to be ABI compatible (same struct size) */
} ErlNifMapIterator;
typedef enum {
ERL_NIF_MAP_ITERATOR_FIRST = 1,
ERL_NIF_MAP_ITERATOR_LAST = 2,
/* deprecated synonyms (undocumented in 17 and 18-rc) */
ERL_NIF_MAP_ITERATOR_HEAD = ERL_NIF_MAP_ITERATOR_FIRST,
ERL_NIF_MAP_ITERATOR_TAIL = ERL_NIF_MAP_ITERATOR_LAST
} ErlNifMapIteratorEntry;
typedef enum {
ERL_NIF_UNIQUE_POSITIVE = (1 << 0),
ERL_NIF_UNIQUE_MONOTONIC = (1 << 1)
} ErlNifUniqueInteger;
typedef enum {
ERL_NIF_BIN2TERM_SAFE = 0x20000000
} ErlNifBinaryToTerm;
typedef enum {
ERL_NIF_INTERNAL_HASH = 1,
ERL_NIF_PHASH2 = 2
} ErlNifHash;
#define ERL_NIF_IOVEC_SIZE 16
typedef struct erl_nif_io_vec {
int iovcnt; /* length of vectors */
size_t size; /* total size in bytes */
SysIOVec *iov;
/* internals (avert your eyes) */
void **ref_bins; /* Binary[] */
int flags;
/* Used when stack allocating the io vec */
SysIOVec small_iov[ERL_NIF_IOVEC_SIZE];
void *small_ref_bin[ERL_NIF_IOVEC_SIZE];
} ErlNifIOVec;
typedef struct erts_io_queue ErlNifIOQueue;
typedef enum {
ERL_NIF_IOQ_NORMAL = 1
} ErlNifIOQueueOpts;
typedef enum {
ERL_NIF_TERM_TYPE_ATOM = 1,
ERL_NIF_TERM_TYPE_BITSTRING = 2,
ERL_NIF_TERM_TYPE_FLOAT = 3,
ERL_NIF_TERM_TYPE_FUN = 4,
ERL_NIF_TERM_TYPE_INTEGER = 5,
ERL_NIF_TERM_TYPE_LIST = 6,
ERL_NIF_TERM_TYPE_MAP = 7,
ERL_NIF_TERM_TYPE_PID = 8,
ERL_NIF_TERM_TYPE_PORT = 9,
ERL_NIF_TERM_TYPE_REFERENCE = 10,
ERL_NIF_TERM_TYPE_TUPLE = 11,
/* This is a dummy value intended to coax the compiler into warning about
* unhandled values in a switch even if all the above values have been
* handled. We can add new entries at any time so the user must always
* have a default case. */
ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1
} ErlNifTermType;
/*
* Return values from enif_thread_type(). Negative values
* reserved for specific types of non-scheduler threads.
* Positive values reserved for scheduler thread types.
*/
#define ERL_NIF_THR_UNDEFINED 0
#define ERL_NIF_THR_NORMAL_SCHEDULER 1
#define ERL_NIF_THR_DIRTY_CPU_SCHEDULER 2
#define ERL_NIF_THR_DIRTY_IO_SCHEDULER 3
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS
typedef struct {
# include "erl_nif_api_funcs.h"
void* erts_alc_test;
} TWinDynNifCallbacks;
extern TWinDynNifCallbacks WinDynNifCallbacks;
# undef ERL_NIF_API_FUNC_DECL
#endif
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF)
# define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME)
# include "erl_nif_api_funcs.h"
/* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */
#else /* non windows or included from emulator itself */
# define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS
# include "erl_nif_api_funcs.h"
# undef ERL_NIF_API_FUNC_DECL
#endif
#if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_))
# define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks;
# define ERL_NIF_INIT_ARGS TWinDynNifCallbacks* callbacks
# define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks))
# define ERL_NIF_INIT_EXPORT __declspec(dllexport)
#else
# define ERL_NIF_INIT_GLOB
# define ERL_NIF_INIT_ARGS void
# define ERL_NIF_INIT_BODY
# if defined(__GNUC__) && __GNUC__ >= 4
# define ERL_NIF_INIT_EXPORT __attribute__ ((visibility("default")))
# elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550)
# define ERL_NIF_INIT_EXPORT __global
# else
# define ERL_NIF_INIT_EXPORT
# endif
#endif
#ifdef STATIC_ERLANG_NIF
# define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(ERL_NIF_INIT_ARGS)
#else
# define ERL_NIF_INIT_DECL(MODNAME) ERL_NIF_INIT_EXPORT ErlNifEntry* nif_init(ERL_NIF_INIT_ARGS)
#endif
#ifdef __cplusplus
}
# define ERL_NIF_INIT_PROLOGUE extern "C" {
# define ERL_NIF_INIT_EPILOGUE }
#else
# define ERL_NIF_INIT_PROLOGUE
# define ERL_NIF_INIT_EPILOGUE
#endif
#define ERL_NIF_INIT(NAME, FUNCS, LOAD, RELOAD, UPGRADE, UNLOAD) \
ERL_NIF_INIT_PROLOGUE \
ERL_NIF_INIT_GLOB \
ERL_NIF_INIT_DECL(NAME); \
ERL_NIF_INIT_DECL(NAME) \
{ \
static ErlNifEntry entry = \
{ \
ERL_NIF_MAJOR_VERSION, \
ERL_NIF_MINOR_VERSION, \
#NAME, \
sizeof(FUNCS) / sizeof(*FUNCS), \
FUNCS, \
LOAD, RELOAD, UPGRADE, UNLOAD, \
ERL_NIF_VM_VARIANT, \
1, \
sizeof(ErlNifResourceTypeInit), \
ERL_NIF_MIN_ERTS_VERSION \
}; \
ERL_NIF_INIT_BODY; \
return &entry; \
} \
ERL_NIF_INIT_EPILOGUE
#if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP))
#define HAVE_USE_DTRACE 1
#endif
#ifdef HAVE_USE_DTRACE
ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM erl_nif_user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
#endif
#endif /* __ERL_NIF_H__ */