1 /* 2 * %CopyrightBegin% 3 * 4 * Copyright Ericsson AB 2009-2020. All Rights Reserved. 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 * 18 * %CopyrightEnd% 19 */ 20 21 /* Include file for writers of Native Implemented Functions. 22 */ 23 24 #ifndef __ERL_NIF_H__ 25 #define __ERL_NIF_H__ 26 27 #ifdef HAVE_CONFIG_H 28 # include "config.h" 29 #endif 30 31 #include "erl_drv_nif.h" 32 33 /* Version history: 34 ** 0.1: R13B03 35 ** 1.0: R13B04 36 ** 2.0: R14A 37 ** 2.1: R14B02 "vm_variant" 38 ** 2.2: R14B03 enif_is_exception 39 ** 2.3: R15 enif_make_reverse_list, enif_is_number 40 ** 2.4: R16 enif_consume_timeslice 41 ** 2.5: First experimental maps API additions (libs of this version is not compatible with any other VM) 42 ** 2.5: R17 Maps API additions 43 ** 2.6: R17 with maps 44 ** R17 dirty schedulers 45 ** 2.7: 17.3 add enif_schedule_nif 46 ** remove enif_schedule_dirty_nif, enif_schedule_dirty_nif_finalizer, enif_dirty_nif_finalizer 47 ** add ErlNifEntry options 48 ** add ErlNifFunc flags 49 ** 2.8: 18.0 add enif_has_pending_exception 50 ** 2.9: 18.2 enif_getenv 51 ** 2.10: Time API 52 ** 2.11: 19.0 enif_snprintf 53 ** 2.12: 20.0 add enif_select, enif_open_resource_type_x 54 ** 2.13: 20.1 add enif_ioq 55 ** 2.14: 21.0 add enif_ioq_peek_head, enif_(mutex|cond|rwlock|thread)_name 56 ** enif_vfprintf, enif_vsnprintf, enif_make_map_from_arrays 57 ** 2.15: 22.0 ERL_NIF_SELECT_CANCEL, enif_select_(read|write) 58 ** enif_term_type 59 ** 2.16: 24.0 enif_init_resource_type, enif_dynamic_resource_call 60 */ 61 #define ERL_NIF_MAJOR_VERSION 2 62 #define ERL_NIF_MINOR_VERSION 16 63 64 /* 65 * WHEN CHANGING INTERFACE VERSION, also replace erts version below with 66 * a ticket number e.g. "erts-@OTP-12345@". The syntax is the same as for 67 * runtime dependencies so multiple tickets should be separated with ":", e.g. 68 * "erts-@OTP-12345:OTP-54321@". 69 * 70 * If you're not on the OTP team, you should use a placeholder like 71 * erts-@MyName@ instead. 72 */ 73 #define ERL_NIF_MIN_ERTS_VERSION "erts-12.0" 74 75 /* 76 * The emulator will refuse to load a nif-lib with a major version 77 * lower than ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD. The load 78 * may however fail if user have not removed use of deprecated 79 * symbols. 80 * 81 * The ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD have to allow 82 * loading of nif-libs built at least two major OTP releases 83 * ago. 84 */ 85 #define ERL_NIF_MIN_REQUIRED_MAJOR_VERSION_ON_LOAD 2 86 87 #include <stdlib.h> 88 #include <stdio.h> 89 #include <stdarg.h> 90 91 #ifdef __cplusplus 92 extern "C" { 93 #endif 94 95 typedef ErlNapiUInt64 ErlNifUInt64; 96 typedef ErlNapiSInt64 ErlNifSInt64; 97 typedef ErlNapiUInt ErlNifUInt; 98 typedef ErlNapiSInt ErlNifSInt; 99 100 #define ERL_NIF_VM_VARIANT "beam.vanilla" 101 typedef ErlNifUInt ERL_NIF_TERM; 102 103 typedef ERL_NIF_TERM ERL_NIF_UINT; 104 105 typedef ErlNifSInt64 ErlNifTime; 106 107 #define ERL_NIF_TIME_ERROR ((ErlNifSInt64) ERTS_NAPI_TIME_ERROR__) 108 109 typedef enum { 110 ERL_NIF_SEC = ERTS_NAPI_SEC__, 111 ERL_NIF_MSEC = ERTS_NAPI_MSEC__, 112 ERL_NIF_USEC = ERTS_NAPI_USEC__, 113 ERL_NIF_NSEC = ERTS_NAPI_NSEC__ 114 } ErlNifTimeUnit; 115 116 struct enif_environment_t; 117 typedef struct enif_environment_t ErlNifEnv; 118 119 typedef struct enif_func_t 120 { 121 const char* name; 122 unsigned arity; 123 ERL_NIF_TERM (*fptr)(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 124 unsigned flags; 125 }ErlNifFunc; 126 127 128 typedef struct enif_entry_t 129 { 130 int major; 131 int minor; 132 const char* name; 133 int num_of_funcs; 134 ErlNifFunc* funcs; 135 int (*load) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); 136 int (*reload) (ErlNifEnv*, void** priv_data, ERL_NIF_TERM load_info); 137 int (*upgrade)(ErlNifEnv*, void** priv_data, void** old_priv_data, ERL_NIF_TERM load_info); 138 void (*unload) (ErlNifEnv*, void* priv_data); 139 140 /* Added in 2.1 */ 141 const char* vm_variant; 142 143 /* Added in 2.7 */ 144 unsigned options; /* Unused. Can be set to 0 or 1 (dirty sched config) */ 145 146 /* Added in 2.12 */ 147 size_t sizeof_ErlNifResourceTypeInit; 148 149 /* Added in 2.14 */ 150 const char* min_erts; 151 }ErlNifEntry; 152 153 154 typedef struct 155 { 156 size_t size; 157 unsigned char* data; 158 159 /* Internals (avert your eyes) */ 160 void* ref_bin; 161 /* for future additions to be ABI compatible (same struct size) */ 162 void* __spare__[2]; 163 }ErlNifBinary; 164 165 #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) 166 typedef void* ErlNifEvent; /* FIXME: Use 'HANDLE' somehow without breaking existing source */ 167 #else 168 typedef int ErlNifEvent; 169 #endif 170 171 /* Return bits from enif_select: */ 172 #define ERL_NIF_SELECT_STOP_CALLED (1 << 0) 173 #define ERL_NIF_SELECT_STOP_SCHEDULED (1 << 1) 174 #define ERL_NIF_SELECT_INVALID_EVENT (1 << 2) 175 #define ERL_NIF_SELECT_FAILED (1 << 3) 176 #define ERL_NIF_SELECT_READ_CANCELLED (1 << 4) 177 #define ERL_NIF_SELECT_WRITE_CANCELLED (1 << 5) 178 #define ERL_NIF_SELECT_ERROR_CANCELLED (1 << 6) 179 #define ERL_NIF_SELECT_NOTSUP (1 << 7) 180 181 typedef enum 182 { 183 ERL_NIF_RT_CREATE = 1, 184 ERL_NIF_RT_TAKEOVER = 2 185 }ErlNifResourceFlags; 186 187 typedef enum 188 { 189 ERL_NIF_LATIN1 = 1 190 }ErlNifCharEncoding; 191 192 typedef struct 193 { 194 ERL_NIF_TERM pid; /* internal, may change */ 195 } ErlNifPid; 196 197 typedef struct 198 { 199 ERL_NIF_TERM port_id; /* internal, may change */ 200 }ErlNifPort; 201 202 typedef ErlDrvMonitor ErlNifMonitor; 203 204 typedef struct enif_resource_type_t ErlNifResourceType; 205 typedef void ErlNifResourceDtor(ErlNifEnv*, void*); 206 typedef void ErlNifResourceStop(ErlNifEnv*, void*, ErlNifEvent, int is_direct_call); 207 typedef void ErlNifResourceDown(ErlNifEnv*, void*, ErlNifPid*, ErlNifMonitor*); 208 typedef void ErlNifResourceDynCall(ErlNifEnv*, void* obj, void* call_data); 209 210 typedef struct { 211 ErlNifResourceDtor* dtor; 212 ErlNifResourceStop* stop; /* at ERL_NIF_SELECT_STOP event */ 213 ErlNifResourceDown* down; /* enif_monitor_process */ 214 int members; 215 ErlNifResourceDynCall* dyncall; 216 } ErlNifResourceTypeInit; 217 218 typedef ErlDrvSysInfo ErlNifSysInfo; 219 220 typedef struct ErlDrvTid_ *ErlNifTid; 221 typedef struct ErlDrvMutex_ ErlNifMutex; 222 typedef struct ErlDrvCond_ ErlNifCond; 223 typedef struct ErlDrvRWLock_ ErlNifRWLock; 224 typedef int ErlNifTSDKey; 225 226 typedef ErlDrvThreadOpts ErlNifThreadOpts; 227 228 typedef enum 229 { 230 ERL_NIF_DIRTY_JOB_CPU_BOUND = ERL_DIRTY_JOB_CPU_BOUND, 231 ERL_NIF_DIRTY_JOB_IO_BOUND = ERL_DIRTY_JOB_IO_BOUND 232 }ErlNifDirtyTaskFlags; 233 234 typedef struct /* All fields all internal and may change */ 235 { 236 ERL_NIF_TERM map; 237 ERL_NIF_UINT size; 238 ERL_NIF_UINT idx; 239 union { 240 struct { 241 ERL_NIF_TERM *ks; 242 ERL_NIF_TERM *vs; 243 }flat; 244 struct { 245 struct ErtsDynamicWStack_* wstack; 246 ERL_NIF_TERM* kv; 247 }hash; 248 }u; 249 void* __spare__[2]; /* for future additions to be ABI compatible (same struct size) */ 250 } ErlNifMapIterator; 251 252 typedef enum { 253 ERL_NIF_MAP_ITERATOR_FIRST = 1, 254 ERL_NIF_MAP_ITERATOR_LAST = 2, 255 256 /* deprecated synonyms (undocumented in 17 and 18-rc) */ 257 ERL_NIF_MAP_ITERATOR_HEAD = ERL_NIF_MAP_ITERATOR_FIRST, 258 ERL_NIF_MAP_ITERATOR_TAIL = ERL_NIF_MAP_ITERATOR_LAST 259 } ErlNifMapIteratorEntry; 260 261 typedef enum { 262 ERL_NIF_UNIQUE_POSITIVE = (1 << 0), 263 ERL_NIF_UNIQUE_MONOTONIC = (1 << 1) 264 } ErlNifUniqueInteger; 265 266 typedef enum { 267 ERL_NIF_BIN2TERM_SAFE = 0x20000000 268 } ErlNifBinaryToTerm; 269 270 typedef enum { 271 ERL_NIF_INTERNAL_HASH = 1, 272 ERL_NIF_PHASH2 = 2 273 } ErlNifHash; 274 275 #define ERL_NIF_IOVEC_SIZE 16 276 277 typedef struct erl_nif_io_vec { 278 int iovcnt; /* length of vectors */ 279 size_t size; /* total size in bytes */ 280 SysIOVec *iov; 281 282 /* internals (avert your eyes) */ 283 void **ref_bins; /* Binary[] */ 284 int flags; 285 286 /* Used when stack allocating the io vec */ 287 SysIOVec small_iov[ERL_NIF_IOVEC_SIZE]; 288 void *small_ref_bin[ERL_NIF_IOVEC_SIZE]; 289 } ErlNifIOVec; 290 291 typedef struct erts_io_queue ErlNifIOQueue; 292 293 typedef enum { 294 ERL_NIF_IOQ_NORMAL = 1 295 } ErlNifIOQueueOpts; 296 297 typedef enum { 298 ERL_NIF_TERM_TYPE_ATOM = 1, 299 ERL_NIF_TERM_TYPE_BITSTRING = 2, 300 ERL_NIF_TERM_TYPE_FLOAT = 3, 301 ERL_NIF_TERM_TYPE_FUN = 4, 302 ERL_NIF_TERM_TYPE_INTEGER = 5, 303 ERL_NIF_TERM_TYPE_LIST = 6, 304 ERL_NIF_TERM_TYPE_MAP = 7, 305 ERL_NIF_TERM_TYPE_PID = 8, 306 ERL_NIF_TERM_TYPE_PORT = 9, 307 ERL_NIF_TERM_TYPE_REFERENCE = 10, 308 ERL_NIF_TERM_TYPE_TUPLE = 11, 309 310 /* This is a dummy value intended to coax the compiler into warning about 311 * unhandled values in a switch even if all the above values have been 312 * handled. We can add new entries at any time so the user must always 313 * have a default case. */ 314 ERL_NIF_TERM_TYPE__MISSING_DEFAULT_CASE__READ_THE_MANUAL = -1 315 } ErlNifTermType; 316 317 /* 318 * Return values from enif_thread_type(). Negative values 319 * reserved for specific types of non-scheduler threads. 320 * Positive values reserved for scheduler thread types. 321 */ 322 323 #define ERL_NIF_THR_UNDEFINED 0 324 #define ERL_NIF_THR_NORMAL_SCHEDULER 1 325 #define ERL_NIF_THR_DIRTY_CPU_SCHEDULER 2 326 #define ERL_NIF_THR_DIRTY_IO_SCHEDULER 3 327 328 #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) 329 # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) RET_TYPE (*NAME) ARGS 330 typedef struct { 331 # include "erl_nif_api_funcs.h" 332 void* erts_alc_test; 333 } TWinDynNifCallbacks; 334 extern TWinDynNifCallbacks WinDynNifCallbacks; 335 # undef ERL_NIF_API_FUNC_DECL 336 #endif 337 338 #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) && !defined(STATIC_ERLANG_DRIVER) && !defined(STATIC_ERLANG_NIF) 339 # define ERL_NIF_API_FUNC_MACRO(NAME) (WinDynNifCallbacks.NAME) 340 # include "erl_nif_api_funcs.h" 341 /* note that we have to keep ERL_NIF_API_FUNC_MACRO defined */ 342 343 #else /* non windows or included from emulator itself */ 344 345 # define ERL_NIF_API_FUNC_DECL(RET_TYPE, NAME, ARGS) extern RET_TYPE NAME ARGS 346 # include "erl_nif_api_funcs.h" 347 # undef ERL_NIF_API_FUNC_DECL 348 #endif 349 350 #if (defined(__WIN32__) || defined(_WIN32) || defined(_WIN32_)) 351 # define ERL_NIF_INIT_GLOB TWinDynNifCallbacks WinDynNifCallbacks; 352 # define ERL_NIF_INIT_ARGS TWinDynNifCallbacks* callbacks 353 # define ERL_NIF_INIT_BODY memcpy(&WinDynNifCallbacks,callbacks,sizeof(TWinDynNifCallbacks)) 354 # define ERL_NIF_INIT_EXPORT __declspec(dllexport) 355 #else 356 # define ERL_NIF_INIT_GLOB 357 # define ERL_NIF_INIT_ARGS void 358 # define ERL_NIF_INIT_BODY 359 # if defined(__GNUC__) && __GNUC__ >= 4 360 # define ERL_NIF_INIT_EXPORT __attribute__ ((visibility("default"))) 361 # elif defined (__SUNPRO_C) && (__SUNPRO_C >= 0x550) 362 # define ERL_NIF_INIT_EXPORT __global 363 # else 364 # define ERL_NIF_INIT_EXPORT 365 # endif 366 #endif 367 368 #ifdef STATIC_ERLANG_NIF 369 # define ERL_NIF_INIT_DECL(MODNAME) ErlNifEntry* MODNAME ## _nif_init(ERL_NIF_INIT_ARGS) 370 #else 371 # define ERL_NIF_INIT_DECL(MODNAME) ERL_NIF_INIT_EXPORT ErlNifEntry* nif_init(ERL_NIF_INIT_ARGS) 372 #endif 373 374 #ifdef __cplusplus 375 } 376 # define ERL_NIF_INIT_PROLOGUE extern "C" { 377 # define ERL_NIF_INIT_EPILOGUE } 378 #else 379 # define ERL_NIF_INIT_PROLOGUE 380 # define ERL_NIF_INIT_EPILOGUE 381 #endif 382 383 384 #define ERL_NIF_INIT(NAME, FUNCS, LOAD, RELOAD, UPGRADE, UNLOAD) \ 385 ERL_NIF_INIT_PROLOGUE \ 386 ERL_NIF_INIT_GLOB \ 387 ERL_NIF_INIT_DECL(NAME); \ 388 ERL_NIF_INIT_DECL(NAME) \ 389 { \ 390 static ErlNifEntry entry = \ 391 { \ 392 ERL_NIF_MAJOR_VERSION, \ 393 ERL_NIF_MINOR_VERSION, \ 394 #NAME, \ 395 sizeof(FUNCS) / sizeof(*FUNCS), \ 396 FUNCS, \ 397 LOAD, RELOAD, UPGRADE, UNLOAD, \ 398 ERL_NIF_VM_VARIANT, \ 399 1, \ 400 sizeof(ErlNifResourceTypeInit), \ 401 ERL_NIF_MIN_ERTS_VERSION \ 402 }; \ 403 ERL_NIF_INIT_BODY; \ 404 return &entry; \ 405 } \ 406 ERL_NIF_INIT_EPILOGUE 407 408 #if defined(USE_DYNAMIC_TRACE) && (defined(USE_DTRACE) || defined(USE_SYSTEMTAP)) 409 #define HAVE_USE_DTRACE 1 410 #endif 411 412 #ifdef HAVE_USE_DTRACE 413 ERL_NIF_TERM erl_nif_user_trace_s1(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 414 ERL_NIF_TERM erl_nif_user_trace_i4s4(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 415 ERL_NIF_TERM erl_nif_user_trace_n(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]); 416 #endif 417 418 #endif /* __ERL_NIF_H__ */ 419 420