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