1 /*
2  * %CopyrightBegin%
3  *
4  * Copyright Ericsson AB 1996-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 #ifndef __GLOBAL_H__
22 #define __GLOBAL_H__
23 
24 #include "sys.h"
25 #include <stddef.h> /* offsetof() */
26 #include "erl_alloc.h"
27 #include "erl_vm.h"
28 #include "erl_node_container_utils.h"
29 #include "hash.h"
30 #include "index.h"
31 #include "atom.h"
32 #include "code_ix.h"
33 #include "export.h"
34 #include "module.h"
35 #include "register.h"
36 #include "erl_fun.h"
37 #include "erl_node_tables.h"
38 #include "erl_process.h"
39 #include "erl_sys_driver.h"
40 #include "erl_debug.h"
41 #include "error.h"
42 #include "erl_utils.h"
43 #include "erl_port.h"
44 #include "erl_gc.h"
45 #include "erl_nif.h"
46 #define ERTS_BINARY_TYPES_ONLY__
47 #include "erl_binary.h"
48 #undef ERTS_BINARY_TYPES_ONLY__
49 
50 struct enif_func_t;
51 
52 #ifdef  DEBUG
53 #  define ERTS_NIF_ASSERT_IN_ENV
54 #endif
55 struct enif_environment_t /* ErlNifEnv */
56 {
57     struct erl_module_nif* mod_nif;
58     Process* proc;
59     Eterm* hp;
60     Eterm* hp_end;
61     ErlHeapFragment* heap_frag;
62     struct enif_tmp_obj_t* tmp_obj_list;
63     int exception_thrown; /* boolean */
64     Process *tracee;
65     int exiting; /* boolean (dirty nifs might return in exiting state) */
66 
67 #ifdef ERTS_NIF_ASSERT_IN_ENV
68     int dbg_disable_assert_in_env;
69 #endif
70 };
71 struct enif_resource_type_t
72 {
73     struct enif_resource_type_t* next;   /* list of all resource types */
74     struct enif_resource_type_t* prev;
75     struct erl_module_nif* owner;  /* that created this type and thus implements the destructor*/
76     ErlNifResourceTypeInit fn;
77     ErlNifResourceTypeInit fn_real;
78     erts_refc_t refc;  /* num of resources of this type (HOTSPOT warning)
79                           +1 for active erl_module_nif */
80     Eterm module;
81     Eterm name;
82 };
83 
84 typedef struct
85 {
86     erts_mtx_t lock;
87     ErtsMonitor* root;
88     Uint refc;
89     size_t user_data_sz;
90 } ErtsResourceMonitors;
91 
92 typedef struct ErtsResource_
93 {
94     struct enif_resource_type_t* type;
95     ErtsResourceMonitors* monitors;
96 #ifdef DEBUG
97     erts_refc_t nif_refc;
98 #else
99 # ifdef ARCH_32
100     byte align__[4];
101 # endif
102 #endif
103     char data[1];
104 }ErtsResource;
105 
106 #define DATA_TO_RESOURCE(PTR) ErtsContainerStruct(PTR, ErtsResource, data)
107 #define erts_resource_ref_size(P) ERTS_MAGIC_REF_THING_SIZE
108 
109 extern Eterm erts_bld_resource_ref(Eterm** hp, ErlOffHeap*, ErtsResource*);
110 
111 extern ErtsCodePtr erts_call_nif_early(Process* c_p, const ErtsCodeInfo* ci);
112 extern void erts_pre_nif(struct enif_environment_t*, Process*,
113 			 struct erl_module_nif*, Process* tracee);
114 extern void erts_post_nif(struct enif_environment_t* env);
115 #ifdef DEBUG
116 int erts_dbg_is_resource_dying(ErtsResource*);
117 #endif
118 extern void erts_resource_stop(ErtsResource*, ErlNifEvent, int is_direct_call);
119 void erts_fire_nif_monitor(ErtsMonitor *tmon);
120 void erts_nif_demonitored(ErtsResource* resource);
121 extern void erts_add_taint(Eterm mod_atom);
122 extern Eterm erts_nif_taints(Process* p);
123 extern void erts_print_nif_taints(fmtfn_t to, void* to_arg);
124 
125 /* Loads the specified NIF. The caller must have code write permission. */
126 Eterm erts_load_nif(Process *c_p, ErtsCodePtr I, Eterm filename, Eterm args);
127 
128 void erts_unload_nif(struct erl_module_nif* nif);
129 extern void erl_nif_init(void);
130 extern int erts_nif_get_funcs(struct erl_module_nif*,
131                               struct enif_func_t **funcs);
132 extern Module *erts_nif_get_module(struct erl_module_nif*);
133 extern Eterm erts_nif_call_function(Process *p, Process *tracee,
134                                     struct erl_module_nif*,
135                                     struct enif_func_t *,
136                                     int argc, Eterm *argv);
137 
138 int erts_call_dirty_nif(ErtsSchedulerData *esdp, Process *c_p,
139                         ErtsCodePtr I, Eterm *reg);
140 ErtsMessage* erts_create_message_from_nif_env(ErlNifEnv* msg_env);
141 
142 
143 /* Driver handle (wrapper for old plain handle) */
144 #define ERL_DE_OK      0
145 #define ERL_DE_UNLOAD  1
146 #define ERL_DE_FORCE_UNLOAD 2
147 #define ERL_DE_RELOAD  3
148 #define ERL_DE_FORCE_RELOAD  4
149 #define ERL_DE_PERMANENT 5
150 
151 #define ERL_DE_PROC_LOADED 0
152 #define ERL_DE_PROC_AWAIT_UNLOAD 1
153 #define ERL_DE_PROC_AWAIT_UNLOAD_ONLY 2
154 #define ERL_DE_PROC_AWAIT_LOAD 3
155 
156 /* Flags for process entries */
157 #define ERL_DE_FL_DEREFERENCED 1
158 
159 /* Flags for drivers, put locking policy here /PaN */
160 #define ERL_DE_FL_KILL_PORTS 1
161 
162 #define ERL_FL_CONSISTENT_MASK ( ERL_DE_FL_KILL_PORTS )
163 
164 /* System specific load errors are returned as positive values */
165 #define ERL_DE_NO_ERROR 0
166 #define ERL_DE_LOAD_ERROR_NO_INIT -1
167 #define ERL_DE_LOAD_ERROR_FAILED_INIT -2
168 #define ERL_DE_LOAD_ERROR_BAD_NAME -3
169 #define ERL_DE_LOAD_ERROR_NAME_TO_LONG -4
170 #define ERL_DE_LOAD_ERROR_INCORRECT_VERSION -5
171 #define ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY -6
172 #define ERL_DE_ERROR_UNSPECIFIED -7
173 #define ERL_DE_LOOKUP_ERROR_NOT_FOUND -8
174 #define ERL_DE_DYNAMIC_ERROR_OFFSET -10
175 
176 typedef struct de_proc_entry {
177     Process *proc;                   /* The process... */
178     Uint    awaiting_status;         /* PROC_LOADED == Have loaded the driver
179 			                PROC_AWAIT_UNLOAD == Wants to be notified
180 			                when we have unloaded the driver (was locked)
181 			                PROC_AWAIT_LOAD == Wants to be notified when we
182 			                reloaded the driver (old was locked) */
183     Uint    flags;                   /* ERL_FL_DE_DEREFERENCED when reload in progress */
184     Eterm   heap[ERTS_REF_THING_SIZE];    /* "ref heap" */
185     struct  de_proc_entry *next;
186 } DE_ProcEntry;
187 
188 typedef struct {
189     void         *handle;             /* Handle for DLL or SO (for dyn. drivers). */
190     DE_ProcEntry *procs;              /* List of pids that have loaded this driver,
191 				         or that wait for it to change state */
192     erts_refc_t  refc;                /* Number of ports/processes having
193 					 references to the driver */
194     erts_atomic32_t port_count;   /* Number of ports using the driver */
195     Uint         flags;               /* ERL_DE_FL_KILL_PORTS */
196     int          status;              /* ERL_DE_xxx */
197     char         *full_path;          /* Full path of the driver */
198     char         *reload_full_path;   /* If status == ERL_DE_RELOAD, this contains
199 				         full name of driver (path) */
200     char         *reload_driver_name; /* ... and this contains the driver name */
201     Uint         reload_flags;        /* flags for reloaded driver */
202 } DE_Handle;
203 
204 /*
205  * This structure represents a link to the next driver.
206  */
207 
208 struct erts_driver_t_ {
209     erts_driver_t *next;
210     erts_driver_t *prev;
211     Eterm name_atom;
212     char *name;
213     struct {
214 	int major;
215 	int minor;
216     } version;
217     int flags;
218     DE_Handle *handle;
219     erts_mtx_t *lock;
220     ErlDrvEntry *entry;
221     ErlDrvData (*start)(ErlDrvPort port, char *command, SysDriverOpts* opts);
222     void (*stop)(ErlDrvData drv_data);
223     void (*finish)(void);
224     void (*flush)(ErlDrvData drv_data);
225     void (*output)(ErlDrvData drv_data, char *buf, ErlDrvSizeT len);
226     void (*outputv)(ErlDrvData drv_data, ErlIOVec *ev); /* Might be NULL */
227     ErlDrvSSizeT (*control)(ErlDrvData drv_data, unsigned int command,
228 			    char *buf, ErlDrvSizeT len,
229 			    char **rbuf, ErlDrvSizeT rlen); /* Might be NULL */
230     ErlDrvSSizeT (*call)(ErlDrvData drv_data, unsigned int command,
231 			 char *buf, ErlDrvSizeT len,
232 			 char **rbuf, ErlDrvSizeT rlen, /* Might be NULL */
233 			 unsigned int *flags);
234     void (*ready_input)(ErlDrvData drv_data, ErlDrvEvent event);
235     void (*ready_output)(ErlDrvData drv_data, ErlDrvEvent event);
236     void (*timeout)(ErlDrvData drv_data);
237     void (*ready_async)(ErlDrvData drv_data, ErlDrvThreadData thread_data); /* Might be NULL */
238     void (*process_exit)(ErlDrvData drv_data, ErlDrvMonitor *monitor);
239     void (*stop_select)(ErlDrvEvent event, void*); /* Might be NULL */
240     void (*emergency_close)(ErlDrvData drv_data);  /* Might be NULL */
241 };
242 
243 extern erts_driver_t *driver_list;
244 extern erts_rwmtx_t erts_driver_list_lock;
245 
246 extern void erts_ddll_init(void);
247 extern void erts_ddll_lock_driver(DE_Handle *dh, char *name);
248 
249 /* These are for bookkeeping */
250 extern void erts_ddll_increment_port_count(DE_Handle *dh);
251 extern void erts_ddll_decrement_port_count(DE_Handle *dh);
252 
253 /* These makes things happen, drivers may be scheduled for unload etc */
254 extern void erts_ddll_reference_driver(DE_Handle *dh);
255 extern void erts_ddll_reference_referenced_driver(DE_Handle *dh);
256 extern void erts_ddll_dereference_driver(DE_Handle *dh);
257 
258 extern char *erts_ddll_error(int code);
259 extern void erts_ddll_proc_dead(Process *p, ErtsProcLocks plocks);
260 extern int erts_ddll_driver_ok(DE_Handle *dh);
261 extern void erts_ddll_remove_monitor(Process *p,
262 				     Eterm ref,
263 				     ErtsProcLocks plocks);
264 extern Eterm erts_ddll_monitor_driver(Process *p,
265 				      Eterm description,
266 				      ErtsProcLocks plocks);
267 
268 /*
269  * This structure represents one type of a binary in a process.
270  */
271 
272 typedef struct proc_bin {
273     Eterm thing_word;		/* Subtag REFC_BINARY_SUBTAG. */
274     Uint size;			/* Binary size in bytes. */
275     struct erl_off_heap_header *next;
276     Binary *val;		/* Pointer to Binary structure. */
277     byte *bytes;		/* Pointer to the actual data bytes. */
278     Uint flags;			/* Flag word. */
279 } ProcBin;
280 
281 #define PB_IS_WRITABLE 1	/* Writable (only one reference to ProcBin) */
282 #define PB_ACTIVE_WRITER 2	/* There is an active writer */
283 
284 /*
285  * ProcBin size in Eterm words.
286  */
287 #define PROC_BIN_SIZE (sizeof(ProcBin)/sizeof(Eterm))
288 
289 union erl_off_heap_ptr {
290     struct erl_off_heap_header* hdr;
291     ProcBin *pb;
292     struct erl_fun_thing* fun;
293     struct external_thing_* ext;
294     ErtsMRefThing *mref;
295     Eterm* ep;
296     void* voidp;
297 };
298 
299 /* controls warning mapping in error_logger */
300 
301 extern Eterm node_cookie;
302 
303 extern int erts_backtrace_depth;
304 extern erts_atomic32_t erts_max_gen_gcs;
305 
306 extern int bif_reductions;      /* reductions + fcalls (when doing call_bif) */
307 extern int stackdump_on_exit;
308 
309 /*
310  * Here is an implementation of a lightweight stack.
311  *
312  * Use it like this:
313  *
314  * DECLARE_ESTACK(Stack)	(At the start of a block)
315  * ...
316  * ESTACK_PUSH(Stack, Term)
317  * ...
318  * if (ESTACK_ISEMPTY(Stack)) {
319  *    Stack is empty
320  * } else {
321  *    Term = ESTACK_POP(Stack);
322  *    Process popped Term here
323  * }
324  * ...
325  * DESTROY_ESTACK(Stack)
326  */
327 
328 typedef struct ErtsEStack_ {
329     Eterm* start;
330     Eterm* sp;
331     Eterm* end;
332     Eterm* edefault;
333     ErtsAlcType_t alloc_type;
334 }ErtsEStack;
335 
336 #define DEF_ESTACK_SIZE (16)
337 
338 void erl_grow_estack(ErtsEStack*, Uint need);
339 #define ESTK_CONCAT(a,b) a##b
340 #define ESTK_DEF_STACK(s) ESTK_CONCAT(s,_default_estack)
341 
342 #define ESTACK_DEFAULT_VALUE(estack_default_stack_array, alloc_type)    \
343     (ErtsEStack) {                                                      \
344         estack_default_stack_array,  /* start */                        \
345         estack_default_stack_array,  /* sp */                           \
346         estack_default_stack_array + DEF_ESTACK_SIZE, /* end */         \
347         estack_default_stack_array,  /* default */                      \
348         alloc_type /* alloc_type */                                     \
349     }
350 
351 #define DECLARE_ESTACK(s)				\
352     Eterm ESTK_DEF_STACK(s)[DEF_ESTACK_SIZE];		\
353     ErtsEStack s = {					\
354         ESTK_DEF_STACK(s),  /* start */ 		\
355         ESTK_DEF_STACK(s),  /* sp */			\
356         ESTK_DEF_STACK(s) + DEF_ESTACK_SIZE, /* end */	\
357         ESTK_DEF_STACK(s),  /* default */		\
358         ERTS_ALC_T_ESTACK /* alloc_type */		\
359     }
360 
361 #define ESTACK_CHANGE_ALLOCATOR(s,t)					\
362 do {									\
363     if ((s).start != ESTK_DEF_STACK(s)) {				\
364 	erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator "	\
365 		 "type of active estack\n");				\
366     }									\
367     (s).alloc_type = (t);						\
368  } while (0)
369 
370 #define DESTROY_ESTACK(s)				\
371 do {							\
372     if ((s).start != ESTK_DEF_STACK(s)) {		\
373 	erts_free((s).alloc_type, (s).start); 		\
374     }							\
375 } while(0)
376 
377 #define DESTROY_ESTACK_EXPLICIT_DEFAULT_ARRAY(s, the_estack_default_array) \
378     do {							\
379         if ((s).start != the_estack_default_array) {            \
380             erts_free((s).alloc_type, (s).start); 		\
381         }							\
382     } while(0)
383 
384 /* Allocate an array on the heap and move the stack there if the
385    default array (that is allocated on the heap is used) */
386 #define ENSURE_ESTACK_HEAP_STACK_ARRAY(s, the_estack_default_array)\
387 do {\
388     if ((s).start == the_estack_default_array) {\
389 	UWord _wsz = ESTACK_COUNT(s);\
390         Eterm *_prev_stack_array = s.start;\
391 	(s).start = erts_alloc((s).alloc_type,                          \
392 			       DEF_ESTACK_SIZE * sizeof(Eterm));\
393 	sys_memcpy((s).start, _prev_stack_array, _wsz*sizeof(Eterm));\
394 	(s).sp = (s).start + _wsz;\
395 	(s).end = (s).start + DEF_ESTACK_SIZE;\
396 	(s).alloc_type = (s).alloc_type;\
397     }\
398     (s).edefault = NULL;\
399  } while (0)
400 
401 
402 /*
403  * Do not free the stack after this, it may have pointers into what
404  * was saved in 'dst'.
405  */
406 #define ESTACK_SAVE(s,dst)\
407 do {\
408     if ((s).start == ESTK_DEF_STACK(s)) {\
409 	UWord _wsz = ESTACK_COUNT(s);\
410 	(dst)->start = erts_alloc((s).alloc_type,\
411 				  DEF_ESTACK_SIZE * sizeof(Eterm));\
412 	sys_memcpy((dst)->start, (s).start,_wsz*sizeof(Eterm));\
413 	(dst)->sp = (dst)->start + _wsz;\
414 	(dst)->end = (dst)->start + DEF_ESTACK_SIZE;\
415         (dst)->edefault = NULL;\
416 	(dst)->alloc_type = (s).alloc_type;\
417     } else\
418         *(dst) = (s);\
419  } while (0)
420 
421 #define DESTROY_SAVED_ESTACK(estack)\
422 do {\
423     if ((estack)->start) {\
424 	erts_free((estack)->alloc_type, (estack)->start);\
425 	(estack)->start = NULL;\
426     }\
427 } while(0)
428 
429 #define CLEAR_SAVED_ESTACK(estack) ((void) ((estack)->start = NULL))
430 
431 /*
432  * Use on empty stack, only the allocator can be changed before this.
433  * The src stack is reset to NULL.
434  */
435 #define ESTACK_RESTORE(s, src)			\
436 do {						\
437     ASSERT((s).start == ESTK_DEF_STACK(s));	\
438     (s) = *(src);  /* struct copy */		\
439     (src)->start = NULL;			\
440     ASSERT((s).sp >= (s).start);		\
441     ASSERT((s).sp <= (s).end);			\
442 } while (0)
443 
444 #define ESTACK_IS_STATIC(s) ((s).start == ESTK_DEF_STACK(s))
445 
446 #define ESTACK_PUSH(s, x)			\
447 do {						\
448     if ((s).sp == (s).end) {			\
449 	erl_grow_estack(&(s), 1); 		\
450     }						\
451     *(s).sp++ = (x);				\
452 } while(0)
453 
454 #define ESTACK_PUSH2(s, x, y)			\
455 do {						\
456     if ((s).sp > (s).end - 2) {			\
457 	erl_grow_estack(&(s), 2);		\
458     }						\
459     *(s).sp++ = (x);				\
460     *(s).sp++ = (y);				\
461 } while(0)
462 
463 #define ESTACK_PUSH3(s, x, y, z)		\
464 do {						\
465     if ((s).sp > (s).end - 3) {			\
466 	erl_grow_estack(&s, 3); 		\
467     }						\
468     *(s).sp++ = (x);				\
469     *(s).sp++ = (y);				\
470     *(s).sp++ = (z);				\
471 } while(0)
472 
473 #define ESTACK_PUSH4(s, E1, E2, E3, E4)		\
474 do {						\
475     if ((s).sp > (s).end - 4) {			\
476 	erl_grow_estack(&s, 4);                 \
477     }						\
478     *(s).sp++ = (E1);				\
479     *(s).sp++ = (E2);				\
480     *(s).sp++ = (E3);				\
481     *(s).sp++ = (E4);				\
482 } while(0)
483 
484 #define ESTACK_RESERVE(s, push_cnt)             \
485 do {					        \
486     if ((s).sp > (s).end - (push_cnt)) {	\
487 	erl_grow_estack(&(s), (push_cnt));	\
488     }					        \
489 } while(0)
490 
491 /* Must be preceded by ESTACK_RESERVE */
492 #define ESTACK_FAST_PUSH(s, x)				\
493 do {							\
494     ASSERT((s).sp < (s).end);                           \
495     *s.sp++ = (x);					\
496 } while(0)
497 
498 #define ESTACK_COUNT(s) ((s).sp - (s).start)
499 #define ESTACK_ISEMPTY(s) ((s).sp == (s).start)
500 #define ESTACK_POP(s) (ASSERT(!ESTACK_ISEMPTY(s)),(*(--(s).sp)))
501 
502 
503 /*
504  * WSTACK: same as ESTACK but with UWord instead of Eterm
505  */
506 
507 typedef struct ErtsWStack_ {
508     UWord* wstart;
509     UWord* wsp;
510     UWord* wend;
511     UWord* wdefault;
512     ErtsAlcType_t alloc_type;
513 }ErtsWStack;
514 
515 #define DEF_WSTACK_SIZE (16)
516 
517 void erl_grow_wstack(ErtsWStack*, Uint need);
518 #define WSTK_CONCAT(a,b) a##b
519 #define WSTK_DEF_STACK(s) WSTK_CONCAT(s,_default_wstack)
520 
521 #define WSTACK_DEFAULT_VALUE(wstack_default_stack_array, alloc_type)    \
522     (ErtsWStack) {                                                      \
523         wstack_default_stack_array,  /* start */                        \
524         wstack_default_stack_array,  /* sp */                           \
525         wstack_default_stack_array + DEF_ESTACK_SIZE, /* end */         \
526         wstack_default_stack_array,  /* default */                      \
527         alloc_type /* alloc_type */                                     \
528     }
529 
530 #define WSTACK_DECLARE(s)				\
531     UWord WSTK_DEF_STACK(s)[DEF_WSTACK_SIZE];		\
532     ErtsWStack s = {					\
533         WSTK_DEF_STACK(s),  /* wstart */ 		\
534         WSTK_DEF_STACK(s),  /* wsp */			\
535         WSTK_DEF_STACK(s) + DEF_WSTACK_SIZE, /* wend */	\
536         WSTK_DEF_STACK(s),  /* wdflt */ 		\
537         ERTS_ALC_T_ESTACK /* alloc_type */		\
538     }
539 #define DECLARE_WSTACK WSTACK_DECLARE
540 
541 typedef struct ErtsDynamicWStack_ {
542     UWord default_stack[DEF_WSTACK_SIZE];
543     ErtsWStack ws;
544 }ErtsDynamicWStack;
545 
546 #define WSTACK_INIT(dwsp, ALC_TYPE)                               \
547 do {	 	                                                  \
548     (dwsp)->ws.wstart   = (dwsp)->default_stack;                  \
549     (dwsp)->ws.wsp      = (dwsp)->default_stack;                  \
550     (dwsp)->ws.wend     = (dwsp)->default_stack + DEF_WSTACK_SIZE;\
551     (dwsp)->ws.wdefault = (dwsp)->default_stack;                  \
552     (dwsp)->ws.alloc_type = ALC_TYPE;                             \
553 } while (0)
554 
555 #define WSTACK_CHANGE_ALLOCATOR(s,t)					\
556 do {									\
557     if (s.wstart != WSTK_DEF_STACK(s)) {				\
558 	erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator "	\
559 		 "type of active wstack\n");				\
560     }									\
561     s.alloc_type = (t);							\
562  } while (0)
563 
564 #define WSTACK_DESTROY(s)				\
565 do {							\
566     if (s.wstart != s.wdefault) {		        \
567 	erts_free(s.alloc_type, s.wstart); 		\
568     }							\
569 } while(0)
570 #define DESTROY_WSTACK WSTACK_DESTROY
571 
572 #define DESTROY_WSTACK_EXPLICIT_DEFAULT_ARRAY(s, the_wstack_default_array) \
573     do {                                                                \
574         if ((s).wstart != the_wstack_default_array) {                   \
575             erts_free((s).alloc_type, (s).wstart);                      \
576         }                                                               \
577     } while(0)
578 
579 #define ENSURE_WSTACK_HEAP_STACK_ARRAY(s, the_wstack_default_array)\
580 do {\
581     if ((s).wstart == the_wstack_default_array) {\
582 	UWord _wsz = WSTACK_COUNT(s);\
583         UWord *_prev_stack_array = s.wstart;\
584 	(s).wstart = erts_alloc((s).alloc_type,                          \
585                                 DEF_WSTACK_SIZE * sizeof(UWord));       \
586 	sys_memcpy((s).wstart, _prev_stack_array, _wsz*sizeof(UWord));\
587 	(s).wsp = (s).wstart + _wsz;\
588 	(s).wend = (s).wstart + DEF_WSTACK_SIZE;\
589 	(s).alloc_type = (s).alloc_type;\
590     }\
591     (s).wdefault = NULL;\
592  } while (0)
593 
594 #define WSTACK_DEBUG(s) \
595     do { \
596 	fprintf(stderr, "wstack size   = %ld\r\n", s.wsp - s.wstart); \
597 	fprintf(stderr, "wstack wstart = %p\r\n", s.wstart); \
598 	fprintf(stderr, "wstack wsp    = %p\r\n", s.wsp); \
599     } while(0)
600 
601 /*
602  * Do not free the stack after this, it may have pointers into what
603  * was saved in 'dst'.
604  */
605 #define WSTACK_SAVE(s,dst)\
606 do {\
607     if (s.wstart == WSTK_DEF_STACK(s)) {\
608 	UWord _wsz = WSTACK_COUNT(s);\
609 	(dst)->wstart = erts_alloc(s.alloc_type,\
610 				  DEF_WSTACK_SIZE * sizeof(UWord));\
611 	sys_memcpy((dst)->wstart, s.wstart,_wsz*sizeof(UWord));\
612 	(dst)->wsp = (dst)->wstart + _wsz;\
613 	(dst)->wend = (dst)->wstart + DEF_WSTACK_SIZE;\
614         (dst)->wdefault = NULL;\
615 	(dst)->alloc_type = s.alloc_type;\
616     } else\
617         *(dst) = s;\
618  } while (0)
619 
620 #define DESTROY_SAVED_WSTACK(wstack)\
621 do {\
622     if ((wstack)->wstart) {\
623 	erts_free((wstack)->alloc_type, (wstack)->wstart);\
624 	(wstack)->wstart = NULL;\
625     }\
626 } while(0)
627 
628 #define CLEAR_SAVED_WSTACK(wstack) ((void) ((wstack)->wstart = NULL))
629 
630 /*
631  * Use on empty stack, only the allocator can be changed before this.
632  * The src stack is reset to NULL.
633  */
634 #define WSTACK_RESTORE(s, src)			\
635 do {						\
636     ASSERT(s.wstart == WSTK_DEF_STACK(s));	\
637     s = *(src);  /* struct copy */		\
638     (src)->wstart = NULL;			\
639     ASSERT(s.wsp >= s.wstart);			\
640     ASSERT(s.wsp <= s.wend);			\
641 } while (0)
642 
643 #define WSTACK_IS_STATIC(s) (s.wstart == WSTK_DEF_STACK(s))
644 
645 #define WSTACK_PUSH(s, x)				\
646 do {							\
647     if (s.wsp == s.wend) {				\
648 	erl_grow_wstack(&s, 1); 	                \
649     }							\
650     *s.wsp++ = (x);					\
651 } while(0)
652 
653 #define WSTACK_PUSH2(s, x, y)			\
654 do {						\
655     if (s.wsp > s.wend - 2) {			\
656 	erl_grow_wstack(&s, 2);                 \
657     }						\
658     *s.wsp++ = (x);				\
659     *s.wsp++ = (y);				\
660 } while(0)
661 
662 #define WSTACK_PUSH3(s, x, y, z)		\
663 do {						\
664     if (s.wsp > s.wend - 3) {	                \
665 	erl_grow_wstack(&s, 3);                 \
666     }						\
667     *s.wsp++ = (x);				\
668     *s.wsp++ = (y);				\
669     *s.wsp++ = (z);				\
670 } while(0)
671 
672 #define WSTACK_PUSH4(s, A1, A2, A3, A4)		\
673 do {						\
674     if (s.wsp > s.wend - 4) {	                \
675 	erl_grow_wstack(&s, 4);                 \
676     }						\
677     *s.wsp++ = (A1);				\
678     *s.wsp++ = (A2);				\
679     *s.wsp++ = (A3);				\
680     *s.wsp++ = (A4);				\
681 } while(0)
682 
683 #define WSTACK_PUSH5(s, A1, A2, A3, A4, A5)     \
684 do {						\
685     if (s.wsp > s.wend - 5) {	                \
686 	erl_grow_wstack(&s, 5);                 \
687     }						\
688     *s.wsp++ = (A1);				\
689     *s.wsp++ = (A2);				\
690     *s.wsp++ = (A3);				\
691     *s.wsp++ = (A4);				\
692     *s.wsp++ = (A5);				\
693 } while(0)
694 
695 #define WSTACK_PUSH6(s, A1, A2, A3, A4, A5, A6) \
696 do {						\
697     if (s.wsp > s.wend - 6) {	                \
698 	erl_grow_wstack(&s, 6);                 \
699     }						\
700     *s.wsp++ = (A1);				\
701     *s.wsp++ = (A2);				\
702     *s.wsp++ = (A3);				\
703     *s.wsp++ = (A4);				\
704     *s.wsp++ = (A5);				\
705     *s.wsp++ = (A6);				\
706 } while(0)
707 
708 #define WSTACK_RESERVE(s, push_cnt)             \
709 do {						\
710     if (s.wsp > s.wend - (push_cnt)) { 	        \
711 	erl_grow_wstack(&s, (push_cnt));        \
712     }                                           \
713 } while(0)
714 
715 /* Must be preceded by WSTACK_RESERVE */
716 #define WSTACK_FAST_PUSH(s, x)                  \
717 do {						\
718     ASSERT(s.wsp < s.wend);                     \
719     *s.wsp++ = (x);                             \
720 } while(0)
721 
722 #define WSTACK_COUNT(s) (s.wsp - s.wstart)
723 #define WSTACK_ISEMPTY(s) (s.wsp == s.wstart)
724 #define WSTACK_POP(s) ((ASSERT(s.wsp > s.wstart)),*(--s.wsp))
725 
726 #define WSTACK_ROLLBACK(s, count) (ASSERT(WSTACK_COUNT(s) >= (count)), \
727                                    s.wsp = s.wstart + (count))
728 
729 /* PSTACK - Stack of any type.
730  * Usage:
731  * {
732  * #define PSTACK_TYPE MyType
733  *    PSTACK_DECLARE(s,16);
734  *    MyType *sp = PSTACK_PUSH(s);
735  *
736  *    sp->x = ....
737  *    sp->y = ....
738  *    sp = PSTACK_PUSH(s);
739  *    ...
740  *    sp = PSTACK_POP(s);
741  *    if (PSTACK_IS_EMPTY(s)) {
742  *        // sp is invalid when stack is empty after pop
743  *    }
744  *
745  *    PSTACK_DESTROY(s);
746  * }
747  */
748 
749 
750 typedef struct ErtsPStack_ {
751     byte* pstart;
752     int offs;   /* "stack pointer" as byte offset from pstart */
753     int size;   /* allocated size in bytes */
754     ErtsAlcType_t alloc_type;
755 }ErtsPStack;
756 
757 void erl_grow_pstack(ErtsPStack* s, void* default_pstack, unsigned need_bytes);
758 #define PSTK_CONCAT(a,b) a##b
759 #define PSTK_DEF_STACK(s) PSTK_CONCAT(s,_default_pstack)
760 
761 #define PSTACK_DECLARE(s, DEF_PSTACK_SIZE) \
762 PSTACK_TYPE PSTK_DEF_STACK(s)[DEF_PSTACK_SIZE];                            \
763 ErtsPStack s = { (byte*)PSTK_DEF_STACK(s), /* pstart */                    \
764                  -(int)sizeof(PSTACK_TYPE), /* offs */                     \
765                  DEF_PSTACK_SIZE*sizeof(PSTACK_TYPE), /* size */           \
766                  ERTS_ALC_T_ESTACK   /* alloc_type */                      \
767 }
768 
769 #define PSTACK_CHANGE_ALLOCATOR(s,t)					\
770 do {									\
771     if (s.pstart != (byte*)PSTK_DEF_STACK(s)) {				\
772 	erts_exit(ERTS_ERROR_EXIT, "Internal error - trying to change allocator "	\
773 		 "type of active pstack\n");				\
774     }									\
775     s.alloc_type = (t);							\
776  } while (0)
777 
778 #define PSTACK_DESTROY(s)				\
779 do {							\
780     if (s.pstart != (byte*)PSTK_DEF_STACK(s)) {		\
781 	erts_free(s.alloc_type, s.pstart); 		\
782     }							\
783 } while(0)
784 
785 #define PSTACK_IS_EMPTY(s) (s.offs < 0)
786 
787 #define PSTACK_COUNT(s) ((s.offs + sizeof(PSTACK_TYPE)) / sizeof(PSTACK_TYPE))
788 
789 #define PSTACK_TOP(s) (ASSERT(!PSTACK_IS_EMPTY(s)), \
790                        (PSTACK_TYPE*)(s.pstart + s.offs))
791 
792 #define PSTACK_PUSH(s) 		                                            \
793     (s.offs += sizeof(PSTACK_TYPE),                                         \
794      ((s.offs == s.size) ? erl_grow_pstack(&s, PSTK_DEF_STACK(s),           \
795                                           sizeof(PSTACK_TYPE)) : (void)0),  \
796      ((PSTACK_TYPE*) (s.pstart + s.offs)))
797 
798 #define PSTACK_POP(s) ((s.offs -= sizeof(PSTACK_TYPE)), \
799                        (PSTACK_TYPE*)(s.pstart + s.offs))
800 
801 /*
802  * Do not free the stack after this, it may have pointers into what
803  * was saved in 'dst'.
804  */
805 #define PSTACK_SAVE(s,dst)\
806 do {\
807     if (s.pstart == (byte*)PSTK_DEF_STACK(s)) {\
808 	UWord _pbytes = PSTACK_COUNT(s) * sizeof(PSTACK_TYPE);\
809 	(dst)->pstart = erts_alloc(s.alloc_type,\
810 				   sizeof(PSTK_DEF_STACK(s)));\
811 	sys_memcpy((dst)->pstart, s.pstart, _pbytes);\
812 	(dst)->offs = s.offs;\
813 	(dst)->size = s.size;\
814 	(dst)->alloc_type = s.alloc_type;\
815     } else\
816         *(dst) = s;\
817  } while (0)
818 
819 /*
820  * Use on empty stack, only the allocator can be changed before this.
821  * The src stack is reset to NULL.
822  */
823 #define PSTACK_RESTORE(s, src)			        \
824 do {						        \
825     ASSERT(s.pstart == (byte*)PSTK_DEF_STACK(s));	\
826     s = *(src);  /* struct copy */		        \
827     (src)->pstart = NULL;			        \
828     ASSERT(s.offs >= -(int)sizeof(PSTACK_TYPE));        \
829     ASSERT(s.offs < s.size);			        \
830 } while (0)
831 
832 #define PSTACK_DESTROY_SAVED(pstack)\
833 do {\
834     if ((pstack)->pstart) {\
835 	erts_free((pstack)->alloc_type, (pstack)->pstart);\
836 	(pstack)->pstart = NULL;\
837     }\
838 } while(0)
839 
840 
841 /*
842  *  An implementation of lightweight unbounded queues,
843  *  using a circular dynamic array.
844  *  It does not include support for change_allocator.
845  *
846  *  Use it like this:
847  *
848  *  DECLARE_EQUEUE(Queue)	(At the start of a block)
849  *  ...
850  *  EQUEUE_PUT(Queue, Term)
851  *  ...
852  *  if (EQUEUE_ISEMPTY(Queue)) {
853  *     Queue is empty
854  *  } else {
855  *     Term = EQUEUE_GET(Stack);
856  *     Process popped Term here
857  *  }
858  *  ...
859  *  DESTROY_EQUEUE(Queue)
860  */
861 
862 typedef struct {
863     Eterm* start;
864     Eterm* front;
865     Eterm* back;
866     int possibly_empty;
867     Eterm* end;
868     ErtsAlcType_t alloc_type;
869 } ErtsEQueue;
870 
871 #define DEF_EQUEUE_SIZE (16)
872 
873 void erl_grow_equeue(ErtsEQueue*, Eterm* def_queue);
874 #define EQUE_CONCAT(a,b) a##b
875 #define EQUE_DEF_QUEUE(q) EQUE_CONCAT(q,_default_equeue)
876 
877 #define DECLARE_EQUEUE(q)				\
878     UWord EQUE_DEF_QUEUE(q)[DEF_EQUEUE_SIZE];     	\
879     ErtsEQueue q = {					\
880         EQUE_DEF_QUEUE(q), /* start */			\
881         EQUE_DEF_QUEUE(q), /* front */			\
882         EQUE_DEF_QUEUE(q), /* back */			\
883         1,                 /* possibly_empty */		\
884         EQUE_DEF_QUEUE(q) + DEF_EQUEUE_SIZE, /* end */	\
885         ERTS_ALC_T_ESTACK  /* alloc_type */		\
886     }
887 
888 #define DESTROY_EQUEUE(q)				\
889 do {							\
890     if (q.start != EQUE_DEF_QUEUE(q)) {			\
891       erts_free(q.alloc_type, q.start);			\
892     }							\
893 } while(0)
894 
895 #define EQUEUE_PUT_UNCHECKED(q, x)			\
896 do {							\
897     q.possibly_empty = 0;				\
898     *(q.back) = (x);                    		\
899     if (++(q.back) == q.end) {				\
900 	q.back = q.start;				\
901     }							\
902 } while(0)
903 
904 #define EQUEUE_PUT(q, x)				\
905 do {							\
906     if (q.back == q.front && !q.possibly_empty) {	\
907         erl_grow_equeue(&q, EQUE_DEF_QUEUE(q));		\
908     }							\
909     EQUEUE_PUT_UNCHECKED(q, x);				\
910 } while(0)
911 
912 #define EQUEUE_ISEMPTY(q) (q.back == q.front && q.possibly_empty)
913 
914 ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q);
915 
916 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
erts_equeue_get(ErtsEQueue * q)917 ERTS_GLB_INLINE Eterm erts_equeue_get(ErtsEQueue *q) {
918     Eterm x;
919     q->possibly_empty = 1;
920     x = *(q->front);
921     if (++(q->front) == q->end) {
922         q->front = q->start;
923     }
924     return x;
925 }
926 #endif
927 #define EQUEUE_GET(q) erts_equeue_get(&(q));
928 
929 /* binary.c */
930 
931 void erts_emasculate_writable_binary(ProcBin* pb);
932 Eterm erts_new_heap_binary(Process *p, byte *buf, int len, byte** datap);
933 Eterm erts_new_mso_binary(Process*, byte*, Uint);
934 Eterm new_binary(Process*, const byte*, Uint);
935 Eterm erts_heap_factory_new_binary(ErtsHeapFactory *hfact, byte *buf,
936                                    Uint len, Uint reserve_size);
937 Eterm erts_realloc_binary(Eterm bin, size_t size);
938 Eterm erts_build_proc_bin(ErlOffHeap*, Eterm*, Binary*);
939 
940 /* erl_bif_info.c */
941 
942 Eterm
943 erts_bld_port_info(Eterm **hpp,
944 		   ErlOffHeap *ohp,
945 		   Uint *szp,
946 		   Port *prt,
947 		   Eterm item);
948 Eterm erts_bld_bin_list(Uint **hpp, Uint *szp, ErlOffHeap* oh, Eterm tail);
949 
950 
951 void erts_bif_info_init(void);
952 
953 /* bif.c */
954 
955 void erts_queue_monitor_message(Process *,
956 				ErtsProcLocks*,
957 				Eterm,
958 				Eterm,
959 				Eterm,
960 				Eterm);
961 void erts_init_trap_export(Export* ep, Eterm m, Eterm f, Uint a,
962 			   Eterm (*bif)(Process*, Eterm*, ErtsCodePtr));
963 void erts_init_bif(void);
964 Eterm erl_send(Process *p, Eterm to, Eterm msg);
965 int erts_set_group_leader(Process *proc, Eterm new_gl);
966 
967 /* erl_bif_guard.c */
968 
969 void erts_init_bif_guard(void);
970 Eterm erts_trapping_length_1(Process* p, Eterm* args);
971 
972 /* erl_bif_op.c */
973 
974 Eterm erl_is_function(Process* p, Eterm arg1, Eterm arg2);
975 
976 /* beam_bif_load.c */
977 Eterm erts_check_process_code(Process *c_p, Eterm module, int *redsp, int fcalls);
978 #define ERTS_CLA_SCAN_WORDS_PER_RED 512
979 
980 int erts_check_copy_literals_gc_need(Process *c_p, int *redsp,
981                                      char *literals, Uint lit_bsize);
982 Eterm erts_copy_literals_gc(Process *c_p, int *redsp, int fcalls);
983 
984 Uint32 erts_block_release_literal_area(void);
985 void erts_unblock_release_literal_area(Uint32);
986 
987 void erts_debug_foreach_release_literal_area_off_heap(void (*func)(ErlOffHeap *, void *),
988                                                       void *arg);
989 
990 typedef struct ErtsLiteralArea_ {
991     struct erl_off_heap_header *off_heap;
992     Eterm *end;
993     Eterm start[1]; /* beginning of area */
994 } ErtsLiteralArea;
995 
996 void erts_queue_release_literals(Process *c_p, ErtsLiteralArea* literals);
997 
998 #define ERTS_LITERAL_AREA_ALLOC_SIZE(N) \
999     (sizeof(ErtsLiteralArea) + sizeof(Eterm)*((N) - 1))
1000 #define ERTS_LITERAL_AREA_SIZE(AP) \
1001     (ERTS_LITERAL_AREA_ALLOC_SIZE((AP)->end - (AP)->start))
1002 
1003 extern erts_atomic_t erts_copy_literal_area__;
1004 #define ERTS_COPY_LITERAL_AREA()					\
1005     ((ErtsLiteralArea *) erts_atomic_read_nob(&erts_copy_literal_area__))
1006 extern Process *erts_literal_area_collector;
1007 
1008 extern Process *erts_code_purger;
1009 
1010 /* beam_load.c */
1011 typedef struct {
1012     const ErtsCodeMFA* mfa;     /* Pointer to: Mod, Name, Arity */
1013     Uint needed;                /* Heap space needed for entire tuple */
1014     Uint32 loc;                 /* Location in source code */
1015     const Eterm* fname_ptr;     /* Pointer to fname table */
1016 } FunctionInfo;
1017 
1018 Binary* erts_alloc_loader_state(void);
1019 
1020 /* Return the module name (a tagged atom) for the prepared code in the magic
1021  * binary, or NIL if the binary does not contain prepared code. */
1022 Eterm erts_module_for_prepared_code(Binary* magic);
1023 
1024 /* Return a non-zero value if the prepared module has an on_load function,
1025  * or 0 if it does not. */
1026 Eterm erts_has_code_on_load(Binary* magic);
1027 
1028 Eterm erts_prepare_loading(Binary* loader_state,  Process *c_p,
1029 			   Eterm group_leader, Eterm* modp,
1030 			   byte* code, Uint size);
1031 Eterm erts_finish_loading(Binary* loader_state, Process* c_p,
1032 			  ErtsProcLocks c_p_locks, Eterm* modp);
1033 Eterm erts_preload_module(Process *c_p, ErtsProcLocks c_p_locks,
1034 			  Eterm group_leader, Eterm* mod, byte* code, Uint size);
1035 void init_load(void);
1036 const ErtsCodeMFA* erts_find_function_from_pc(ErtsCodePtr pc);
1037 Eterm* erts_build_mfa_item(FunctionInfo* fi, Eterm* hp,
1038 			   Eterm args, Eterm* mfa_p, Eterm loc_tail);
1039 void erts_set_current_function(FunctionInfo* fi, const ErtsCodeMFA* mfa);
1040 Eterm erts_make_stub_module(Process* p, Eterm Mod, Eterm Beam, Eterm Info);
1041 
1042 /* beam_ranges.c */
1043 void erts_init_ranges(void);
1044 void erts_start_staging_ranges(int num_new);
1045 void erts_end_staging_ranges(int commit);
1046 void erts_update_ranges(const BeamCodeHeader* code, Uint size);
1047 void erts_remove_from_ranges(const BeamCodeHeader* code);
1048 UWord erts_ranges_sz(void);
1049 void erts_lookup_function_info(FunctionInfo* fi,
1050                                ErtsCodePtr pc,
1051                                int full_info);
1052 extern ErtsLiteralArea** erts_dump_lit_areas;
1053 extern Uint erts_dump_num_lit_areas;
1054 
1055 /* break.c */
1056 void init_break_handler(void);
1057 void erts_set_ignore_break(void);
1058 void erts_replace_intr(void);
1059 void process_info(fmtfn_t, void *);
1060 void print_process_info(fmtfn_t, void *, Process*, ErtsProcLocks);
1061 void info(fmtfn_t, void *);
1062 void loaded(fmtfn_t, void *);
1063 void erts_print_base64(fmtfn_t to, void *to_arg, const byte* src, Uint size);
1064 
1065 /* sighandler sys.c */
1066 int erts_set_signal(Eterm signal, Eterm type);
1067 
1068 /* erl_arith.c */
1069 double erts_get_positive_zero_float(void);
1070 
1071 /* config.c */
1072 
1073 __decl_noreturn void __noreturn erts_exit_epilogue(void);
1074 __decl_noreturn void __noreturn erts_exit(int n, const char*, ...);
1075 __decl_noreturn void __noreturn erts_flush_async_exit(int n, char*, ...);
1076 void erl_error(const char*, va_list);
1077 
1078 /* This controls whether sharing-preserving copy is used by Erlang */
1079 
1080 #ifdef SHCOPY
1081 #define SHCOPY_SEND
1082 #define SHCOPY_SPAWN
1083 #endif
1084 
1085 /* The persistent state while the sharing-preserving copier works */
1086 
1087 typedef struct {
1088     Eterm  queue_default[DEF_EQUEUE_SIZE];
1089     Eterm* queue_start;
1090     Eterm* queue_end;
1091     ErtsAlcType_t queue_alloc_type;
1092     UWord  bitstore_default[DEF_WSTACK_SIZE];
1093     UWord* bitstore_start;
1094 #ifdef DEBUG
1095     UWord* bitstore_stop;
1096 #endif
1097     ErtsAlcType_t bitstore_alloc_type;
1098     Eterm  shtable_default[DEF_ESTACK_SIZE];
1099     Eterm* shtable_start;
1100     ErtsAlcType_t shtable_alloc_type;
1101     Uint literal_size;
1102     Eterm *lit_purge_ptr;
1103     Uint lit_purge_sz;
1104     int copy_literals;
1105 } erts_shcopy_t;
1106 
1107 #define INITIALIZE_SHCOPY(info)						\
1108     do {								\
1109 	ErtsLiteralArea *larea__ = ERTS_COPY_LITERAL_AREA();		\
1110 	info.queue_start = info.queue_default;				\
1111 	info.bitstore_start = info.bitstore_default;			\
1112 	info.shtable_start = info.shtable_default;			\
1113 	info.literal_size = 0;						\
1114 	info.copy_literals = 0;						\
1115 	if (larea__) {							\
1116 	    info.lit_purge_ptr = &larea__->start[0];			\
1117 	    info.lit_purge_sz = larea__->end - info.lit_purge_ptr;	\
1118 	}								\
1119 	else {								\
1120 	    info.lit_purge_ptr = NULL;					\
1121 	    info.lit_purge_sz = 0;					\
1122 	}								\
1123     } while(0)
1124 
1125 #define DESTROY_SHCOPY(info)                                            \
1126 do {                                                                    \
1127     if (info.queue_start != info.queue_default) {                       \
1128         erts_free(info.queue_alloc_type, info.queue_start);             \
1129     }                                                                   \
1130     if (info.bitstore_start != info.bitstore_default) {                 \
1131         erts_free(info.bitstore_alloc_type, info.bitstore_start);       \
1132     }                                                                   \
1133     if (info.shtable_start != info.shtable_default) {                   \
1134         erts_free(info.shtable_alloc_type, info.shtable_start);         \
1135     }                                                                   \
1136 } while(0)
1137 
1138 /* copy.c */
1139 typedef struct {
1140     Eterm *lit_purge_ptr;
1141     Uint lit_purge_sz;
1142 } erts_literal_area_t;
1143 
1144 #define INITIALIZE_LITERAL_PURGE_AREA(Area)				\
1145     do {								\
1146 	ErtsLiteralArea *larea__ = ERTS_COPY_LITERAL_AREA();		\
1147 	if (larea__) {							\
1148 	    (Area).lit_purge_ptr = &larea__->start[0];			\
1149 	    (Area).lit_purge_sz = larea__->end - (Area).lit_purge_ptr;	\
1150 	}								\
1151 	else {								\
1152 	    (Area).lit_purge_ptr = NULL;				\
1153 	    (Area).lit_purge_sz = 0;					\
1154 	}								\
1155     } while(0)
1156 
1157 Eterm copy_object_x(Eterm, Process*, Uint);
1158 #define copy_object(Term, Proc) copy_object_x(Term,Proc,0)
1159 
1160 Uint size_object_x(Eterm, erts_literal_area_t*);
1161 #define size_object(Term) size_object_x(Term,NULL)
1162 #define size_object_litopt(Term,LitArea) size_object_x(Term,LitArea)
1163 
1164 Uint copy_shared_calculate(Eterm, erts_shcopy_t*);
1165 Uint size_shared(Eterm);
1166 
1167 /* #define ERTS_COPY_REGISTER_LOCATION */
1168 
1169 #ifdef ERTS_COPY_REGISTER_LOCATION
1170 
1171 #define copy_shared_perform(U, V, X, Y, Z) \
1172     copy_shared_perform_x((U), (V), (X), (Y), (Z), __FILE__, __LINE__)
1173 Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*,
1174                             char *file, int line);
1175 
1176 Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*,
1177                     char *file, int line);
1178 #define copy_struct(Obj,Sz,HPP,OH) \
1179     copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL,__FILE__,__LINE__)
1180 #define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \
1181     copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea,__FILE__,__LINE__)
1182 
1183 #define copy_shallow(R, SZ, HPP, OH) \
1184     copy_shallow_x((R), (SZ), (HPP), (OH), __FILE__, __LINE__)
1185 Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*,
1186                      char *file, int line);
1187 
1188 #else
1189 
1190 #define copy_shared_perform(U, V, X, Y, Z) \
1191     copy_shared_perform_x((U), (V), (X), (Y), (Z))
1192 Eterm copy_shared_perform_x(Eterm, Uint, erts_shcopy_t*, Eterm**, ErlOffHeap*);
1193 
1194 Eterm copy_struct_x(Eterm, Uint, Eterm**, ErlOffHeap*, Uint*, erts_literal_area_t*);
1195 #define copy_struct(Obj,Sz,HPP,OH) \
1196     copy_struct_x(Obj,Sz,HPP,OH,NULL,NULL)
1197 #define copy_struct_litopt(Obj,Sz,HPP,OH,LitArea) \
1198     copy_struct_x(Obj,Sz,HPP,OH,NULL,LitArea)
1199 
1200 #define copy_shallow(R, SZ, HPP, OH) \
1201     copy_shallow_x((R), (SZ), (HPP), (OH))
1202 Eterm copy_shallow_x(Eterm* ERTS_RESTRICT, Uint, Eterm**, ErlOffHeap*);
1203 
1204 #endif
1205 
1206 void erts_move_multi_frags(Eterm** hpp, ErlOffHeap*, ErlHeapFragment* first,
1207 			   Eterm* refs, unsigned nrefs, int literals);
1208 
1209 /* Utilities */
1210 void erts_monitor_nodes_delete(ErtsMonitor *);
1211 extern Eterm erts_monitor_nodes(Process *, Eterm, Eterm);
1212 extern Eterm erts_processes_monitoring_nodes(Process *);
1213 extern int erts_do_net_exits(DistEntry*, Eterm);
1214 extern int distribution_info(fmtfn_t, void *);
1215 extern int is_node_name_atom(Eterm a);
1216 
1217 extern int erts_net_message(Port *, DistEntry *, Uint32 conn_id,
1218 			    byte *, ErlDrvSizeT, Binary *, byte *, ErlDrvSizeT);
1219 
1220 int erts_dist_pend_spawn_exit_delete(ErtsMonitor *mon);
1221 int erts_dist_pend_spawn_exit_parent_setup(ErtsMonitor *mon);
1222 int erts_dist_pend_spawn_exit_parent_wait(Process *c_p,
1223                                           ErtsProcLocks locks,
1224                                           ErtsMonitor *mon);
1225 
1226 extern void init_dist(void);
1227 extern int stop_dist(void);
1228 
1229 void erl_progressf(char* format, ...);
1230 
1231 #ifdef MESS_DEBUG
1232 void print_pass_through(int, byte*, int);
1233 #endif
1234 
1235 /* beam_emu.c */
1236 int catchlevel(Process*);
1237 void init_emulator(void);
1238 void process_main(ErtsSchedulerData *);
1239 void erts_dirty_process_main(ErtsSchedulerData *);
1240 Eterm build_stacktrace(Process* c_p, Eterm exc);
1241 Eterm expand_error_value(Process* c_p, Uint freason, Eterm Value);
1242 void erts_save_stacktrace(Process* p, struct StackTrace* s, int depth);
1243 ErtsCodePtr erts_printable_return_address(Process* p, Eterm *E) ERTS_NOINLINE;
1244 
1245 /* erl_init.c */
1246 
1247 typedef struct {
1248     Eterm delay_time;
1249     int context_reds;
1250 } ErtsModifiedTimings;
1251 
1252 extern Export *erts_delay_trap;
1253 extern int erts_modified_timing_level;
1254 extern ErtsModifiedTimings erts_modified_timings[];
1255 #define ERTS_USE_MODIFIED_TIMING() \
1256   (erts_modified_timing_level >= 0)
1257 #define ERTS_MODIFIED_TIMING_DELAY \
1258   (erts_modified_timings[erts_modified_timing_level].delay_time)
1259 #define ERTS_MODIFIED_TIMING_CONTEXT_REDS \
1260   (erts_modified_timings[erts_modified_timing_level].context_reds)
1261 #define ERTS_MODIFIED_TIMING_INPUT_REDS \
1262   (erts_modified_timings[erts_modified_timing_level].input_reds)
1263 
1264 extern int erts_no_line_info;
1265 extern Eterm erts_error_logger_warnings;
1266 extern int erts_initialized;
1267 extern int erts_compat_rel;
1268 
1269 #ifdef BEAMASM
1270 extern int erts_jit_asm_dump;
1271 #endif
1272 
1273 void erl_start(int, char**);
1274 void erts_usage(void);
1275 Eterm erts_preloaded(Process* p);
1276 
1277 
1278 /* erl_md5.c */
1279 
1280 typedef struct {
1281     Uint32 state[4];		/* state (ABCD) */
1282     Uint32 count[2];		/* number of bits, modulo 2^64 (lsb first) */
1283     unsigned char buffer[64];	/* input buffer */
1284 } MD5_CTX;
1285 
1286 void MD5Init(MD5_CTX *);
1287 void MD5Update(MD5_CTX *, unsigned char *, unsigned int);
1288 void MD5Final(unsigned char [16], MD5_CTX *);
1289 
1290 
1291 /* io.c */
1292 
1293 typedef struct {
1294     char *name;
1295     char *driver_name;
1296 } ErtsPortNames;
1297 
1298 #define ERTS_SPAWN_DRIVER 1
1299 #define ERTS_SPAWN_EXECUTABLE 2
1300 #define ERTS_SPAWN_ANY (ERTS_SPAWN_DRIVER | ERTS_SPAWN_EXECUTABLE)
1301 int erts_add_driver_entry(ErlDrvEntry *drv, DE_Handle *handle, int driver_list_locked, int taint);
1302 void erts_destroy_driver(erts_driver_t *drv);
1303 int erts_save_suspend_process_on_port(Port*, Process*);
1304 Port *erts_open_driver(erts_driver_t*, Eterm, char*, SysDriverOpts*, int *, int *);
1305 void erts_init_io(int, int, int);
1306 void erts_raw_port_command(Port*, byte*, Uint);
1307 void driver_report_exit(ErlDrvPort, int);
1308 LineBuf* allocate_linebuf(int);
1309 int async_ready(Port *, void*);
1310 ErtsPortNames *erts_get_port_names(Eterm, ErlDrvPort);
1311 void erts_free_port_names(ErtsPortNames *);
1312 Uint erts_port_ioq_size(Port *pp);
1313 void erts_stale_drv_select(Eterm, ErlDrvPort, ErlDrvEvent, int, int);
1314 
1315 Port *erts_get_heart_port(void);
1316 void erts_emergency_close_ports(void);
1317 void erts_ref_to_driver_monitor(Eterm ref, ErlDrvMonitor *mon);
1318 Eterm erts_driver_monitor_to_ref(Eterm* hp, const ErlDrvMonitor *mon);
1319 
1320 #if defined(ERTS_ENABLE_LOCK_COUNT)
1321 void erts_lcnt_update_driver_locks(int enable);
1322 void erts_lcnt_update_port_locks(int enable);
1323 #endif
1324 
1325 /* driver_tab.c */
1326 typedef struct {
1327     ErlDrvEntry* de;
1328     int taint;
1329 } ErtsStaticDriver;
1330 typedef void *(*ErtsStaticNifInitFPtr)(void);
1331 typedef struct ErtsStaticNifEntry_ {
1332     const char *nif_name;
1333     ErtsStaticNifInitFPtr nif_init;
1334     int taint;
1335 } ErtsStaticNifEntry;
1336 ErtsStaticNifEntry* erts_static_nif_get_nif_init(const char *name, int len);
1337 int erts_is_static_nif(void *handle);
1338 void erts_init_static_drivers(void);
1339 
1340 /* erl_drv_thread.c */
1341 void erl_drv_thr_init(void);
1342 
1343 /* utils.c */
1344 void erts_cleanup_offheap(ErlOffHeap *offheap);
1345 
1346 Uint64 erts_timestamp_millis(void);
1347 
1348 Export* erts_find_function(Eterm, Eterm, unsigned int, ErtsCodeIndex);
1349 
1350 /* ERTS_NOINLINE prevents link-time optimization across modules */
1351 const void *erts_get_stacklimit(void);
1352 int erts_check_below_limit(char *ptr, char *limit) ERTS_NOINLINE;
1353 int erts_check_above_limit(char *ptr, char *limit) ERTS_NOINLINE;
1354 
1355 void *erts_ptr_id(void *ptr) ERTS_NOINLINE;
1356 int erts_check_if_stack_grows_downwards(char *ptr) ERTS_NOINLINE;
1357 
1358 Eterm store_external_or_ref_in_proc_(Process *, Eterm);
1359 Eterm store_external_or_ref_(Uint **, ErlOffHeap*, Eterm);
1360 
1361 typedef Eterm  (*erts_ycf_continue_fun_t)(long* ycf_number_of_reduction_param,
1362                                           void** ycf_trap_state,
1363                                           void* ycf_extra_context);
1364 typedef void (*erts_ycf_destroy_trap_state_fun_t)(void *trap_state);
1365 typedef Eterm (*erts_ycf_yielding_fun_t)(long* ycf_nr_of_reductions_param,
1366                                          void** ycf_trap_state,
1367                                          void* ycf_extra_context,
1368                                          void* (*ycf_yield_alloc_fun) (size_t,void*),
1369                                          void (*ycf_yield_free_fun) (void*,void*),
1370                                          void* ycf_yield_alloc_free_context,
1371                                          size_t ycf_stack_alloc_size_or_max_size,
1372                                          void* ycf_stack_alloc_data,
1373                                          Process* p,
1374                                          Eterm* bif_args);
1375 Eterm erts_ycf_trap_driver(Process* p,
1376                            Eterm* bif_args,
1377                            int nr_of_arguments,
1378                            int iterations_per_red,
1379                            ErtsAlcType_t memory_allocation_type,
1380                            size_t ycf_stack_alloc_size,
1381                            int export_entry_index,
1382                            erts_ycf_continue_fun_t ycf_continue_fun,
1383                            erts_ycf_destroy_trap_state_fun_t ycf_destroy_fun,
1384                            erts_ycf_yielding_fun_t ycf_yielding_fun);
1385 
1386 /* A quick sort function that is compatible with the qsort function
1387    declared in stdlib.h. We need our own so that we can yield inside
1388    the function */
1389 typedef int (*erts_void_ptr_cmp_t)(const void *, const void *);
1390 void erts_qsort(void *base,
1391                 size_t nr_of_items,
1392                 size_t item_size,
1393                 erts_void_ptr_cmp_t compare);
1394 /* YCF generated functions for yielding of erts_qsort. This means that
1395    the following three functions can be used when one needs a yieldable
1396    sorting function. See
1397    $ERL_TOP/erts/emulator/internal_doc/AutomaticYieldingOfCCode.md for
1398    information about using YCF generated functions.
1399 
1400 
1401    !!!!
1402    Note that the erts_qsort_swap that is used by erts_qsort does
1403    not have yielding enabled. If the array items are large erts_qsort
1404    should also trap in the erts_qsort_swap function, but this causes
1405    terrible performance when the array items are small, so one should
1406    investigate a fast-path approach
1407 */
1408 void erts_qsort_ycf_gen_destroy(void* ycf_my_trap_state);
1409 void  erts_qsort_ycf_gen_continue(long* ycf_number_of_reduction_param,
1410                                   void** ycf_trap_state,
1411                                   void* ycf_extra_context /* Not used, can be NULL */);
1412 void erts_qsort_ycf_gen_yielding(long* ycf_nr_of_reductions_param,
1413                                  void** ycf_trap_state,
1414                                  void* ycf_extra_context, /* Not used, can be NULL */
1415                                  void* (*ycf_yield_alloc_fun) (size_t,void*),
1416                                  void (*ycf_yield_free_fun) (void*,void*),
1417                                  void* ycf_yield_alloc_free_context,
1418                                  size_t ycf_stack_alloc_size_or_max_size,  /* Not used, can be 0 */
1419                                  void* ycf_stack_alloc_data, /* Not used, can be NULL */
1420                                  void *base,
1421                                  size_t nr_of_items,
1422                                  size_t item_size,
1423                                  erts_void_ptr_cmp_t compare);
1424 #if defined(DEBUG)
1425 /*
1426  * ycf_debug_get_stack_start is used in YCF's debug mode (see
1427  * documentation for the -debug flag of the YCF tool). The function
1428  * ycf_debug_set_stack_start sets the value that the function
1429  * ycf_debug_get_stack_start returns for the current thread. The
1430  * function ycf_debug_reset_stack_start sets the value that the
1431  * function ycf_debug_get_stack_start returns to NULL for the current
1432  * thread.
1433  */
1434 void ycf_debug_set_stack_start(void * start);
1435 void ycf_debug_reset_stack_start(void);
1436 void *ycf_debug_get_stack_start(void);
1437 #endif
1438 
1439 #define NC_HEAP_SIZE(NC) \
1440  (ASSERT(is_node_container((NC))), \
1441   IS_CONST((NC)) ? 0 : (thing_arityval(*boxed_val((NC))) + 1))
1442 #define STORE_NC(Hpp, ETpp, NC) \
1443  (ASSERT(is_node_container((NC))), \
1444   IS_CONST((NC)) ? (NC) : store_external_or_ref_((Hpp), (ETpp), (NC)))
1445 #define STORE_NC_IN_PROC(Pp, NC) \
1446  (ASSERT(is_node_container((NC))), \
1447   IS_CONST((NC)) ? (NC) : store_external_or_ref_in_proc_((Pp), (NC)))
1448 
1449 /* duplicates from big.h */
1450 int term_to_Uint(Eterm term, Uint *up);
1451 int term_to_UWord(Eterm, UWord*);
1452 
1453 #ifdef HAVE_ERTS_NOW_CPU
1454 extern int erts_cpu_timestamp;
1455 #endif
1456 /* erl_bif_chksum.c */
1457 void erts_init_bif_chksum(void);
1458 /* erl_bif_re.c */
1459 void erts_init_bif_re(void);
1460 Sint erts_re_set_loop_limit(Sint limit);
1461 /* erl_bif_binary.c */
1462 void erts_init_bif_binary(void);
1463 Sint erts_binary_set_loop_limit(Sint limit);
1464 
1465 /* erl_bif_persistent.c */
1466 void erts_init_bif_persistent_term(void);
1467 void erts_init_persistent_dumping(void);
1468 extern ErtsLiteralArea** erts_persistent_areas;
1469 extern Uint erts_num_persistent_areas;
1470 void erts_debug_foreach_persistent_term_off_heap(void (*func)(ErlOffHeap *, void *),
1471                                                  void *arg);
1472 int erts_debug_have_accessed_literal_area(ErtsLiteralArea *lap);
1473 void erts_debug_save_accessed_literal_area(ErtsLiteralArea *lap);
1474 Eterm erts_debug_persistent_term_xtra_info(Process* c_p);
1475 
1476 /* external.c */
1477 void erts_init_external(void);
1478 
1479 /* erl_map.c */
1480 void erts_init_map(void);
1481 
1482 /* beam_debug.c */
1483 UWord erts_check_stack_recursion_downwards(char *start_c, char *prev_c);
1484 UWord erts_check_stack_recursion_upwards(char *start_c, char *prev_c);
1485 int erts_is_above_stack_limit(char *ptr);
1486 
1487 /* erl_unicode.c */
1488 void erts_init_unicode(void);
1489 Sint erts_unicode_set_loop_limit(Sint limit);
1490 
1491 void erts_native_filename_put(Eterm ioterm, int encoding, byte *p) ;
1492 Sint erts_native_filename_need(Eterm ioterm, int encoding);
1493 void erts_copy_utf8_to_utf16_little(byte *target, byte *bytes, int num_chars);
1494 int erts_analyze_utf8(byte *source, Uint size,
1495 			byte **err_pos, Uint *num_chars, int *left);
1496 int erts_analyze_utf8_x(byte *source, Uint size,
1497 			byte **err_pos, Uint *num_chars, int *left,
1498 			Sint *num_latin1_chars, Uint max_chars);
1499 char *erts_convert_filename_to_native(Eterm name, char *statbuf,
1500 				      size_t statbuf_size,
1501 				      ErtsAlcType_t alloc_type,
1502 				      int allow_empty, int allow_atom,
1503 				      Sint *used /* out */);
1504 char *erts_convert_filename_to_encoding(Eterm name, char *statbuf,
1505 					size_t statbuf_size,
1506 					ErtsAlcType_t alloc_type,
1507 					int allow_empty, int allow_atom,
1508 					int encoding,
1509 					Sint *used /* out */,
1510 					Uint extra);
1511 char* erts_convert_filename_to_wchar(byte* bytes, Uint size,
1512                                      char *statbuf, size_t statbuf_size,
1513                                      ErtsAlcType_t alloc_type, Sint* used,
1514                                      Uint extra_wchars);
1515 Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes);
1516 Eterm erts_utf8_to_list(Process *p, Uint num, byte *bytes, Uint sz, Uint left,
1517 			Uint *num_built, Uint *num_eaten, Eterm tail);
1518 int erts_utf8_to_latin1(byte* dest, const byte* source, int slen);
1519 #define ERTS_UTF8_OK 0
1520 #define ERTS_UTF8_INCOMPLETE 1
1521 #define ERTS_UTF8_ERROR 2
1522 #define ERTS_UTF8_ANALYZE_MORE 3
1523 #define ERTS_UTF8_OK_MAX_CHARS 4
1524 
1525 void bin_write(fmtfn_t, void*, byte*, size_t);
1526 Sint intlist_to_buf(Eterm, char*, Sint); /* most callers pass plain char*'s */
1527 int erts_unicode_list_to_buf(Eterm list, byte *buf, Sint len, Sint* written);
1528 Sint erts_unicode_list_to_buf_len(Eterm list);
1529 
1530 int Sint_to_buf(Sint num, int base, char **buf_p, size_t buf_size);
1531 
1532 #define ERTS_IOLIST_STATE_INITER(C_P, OBJ)	\
1533     {(C_P), 0, 0, (OBJ), {NULL, NULL, NULL, ERTS_ALC_T_INVALID}, 0, 0}
1534 
1535 #define ERTS_IOLIST_STATE_MOVE(TO, FROM)	\
1536     sys_memcpy((void *) (TO), (void *) (FROM), sizeof(ErtsIOListState))
1537 
1538 #define ERTS_IOLIST_SIZE_YIELDS_COUNT_PER_RED 8
1539 
1540 typedef struct {
1541     Process *c_p;
1542     ErlDrvSizeT size;
1543     Uint offs;
1544     Eterm obj;
1545     ErtsEStack estack;
1546     int reds_left;
1547     int have_size;
1548 } ErtsIOListState;
1549 
1550 #define ERTS_IOLIST2BUF_STATE_INITER(C_P, OBJ)	\
1551     {ERTS_IOLIST_STATE_INITER((C_P), (OBJ)), {NULL, 0, 0, 0}, NULL, 0, NULL, 0}
1552 
1553 #define ERTS_IOLIST2BUF_STATE_MOVE(TO, FROM)	\
1554     sys_memcpy((void *) (TO), (void *) (FROM), sizeof(ErtsIOList2BufState))
1555 
1556 #define ERTS_IOLIST_TO_BUF_BYTES_PER_YIELD_COUNT 32
1557 #define ERTS_IOLIST_TO_BUF_YIELD_COUNT_PER_RED 8
1558 #define ERTS_IOLIST_TO_BUF_BYTES_PER_RED \
1559     (ERTS_IOLIST_TO_BUF_YIELD_COUNT_PER_RED*ERTS_IOLIST_TO_BUF_BYTES_PER_YIELD_COUNT)
1560 
1561 typedef struct {
1562     ErtsIOListState iolist;
1563     struct {
1564 	byte *bptr;
1565 	size_t size;
1566 	Uint bitoffs;
1567 	Uint bitsize;
1568     } bcopy;
1569     char *buf;
1570     ErlDrvSizeT len;
1571     Eterm *objp;
1572     int offset;
1573 } ErtsIOList2BufState;
1574 
1575 #define ERTS_IOLIST_OK 0
1576 #define ERTS_IOLIST_OVERFLOW 1
1577 #define ERTS_IOLIST_TYPE 2
1578 #define ERTS_IOLIST_YIELD 3
1579 
1580 Eterm buf_to_intlist(Eterm**, const char*, size_t, Eterm); /* most callers pass plain char*'s */
1581 
1582 #define ERTS_IOLIST_TO_BUF_OVERFLOW	(~((ErlDrvSizeT) 0))
1583 #define ERTS_IOLIST_TO_BUF_TYPE_ERROR	(~((ErlDrvSizeT) 1))
1584 #define ERTS_IOLIST_TO_BUF_YIELD	(~((ErlDrvSizeT) 2))
1585 #define ERTS_IOLIST_TO_BUF_FAILED(R) \
1586     (((R) & (~((ErlDrvSizeT) 3))) == (~((ErlDrvSizeT) 3)))
1587 #define ERTS_IOLIST_TO_BUF_SUCCEEDED(R) \
1588     (!ERTS_IOLIST_TO_BUF_FAILED((R)))
1589 
1590 ErlDrvSizeT erts_iolist_to_buf(Eterm, char*, ErlDrvSizeT);
1591 ErlDrvSizeT erts_iolist_to_buf_yielding(ErtsIOList2BufState *);
1592 int erts_iolist_size_yielding(ErtsIOListState *state);
1593 int erts_iolist_size(Eterm, ErlDrvSizeT *);
1594 Sint is_string(Eterm);
1595 void erl_at_exit(void (*) (void*), void*);
1596 Eterm collect_memory(Process *);
1597 void dump_memory_to_fd(int);
1598 int dump_memory_data(const char *);
1599 
1600 Eterm erts_unary_minus(Process* p, Eterm arg1);
1601 Eterm erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2);
1602 Eterm erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2);
1603 Eterm erts_mixed_times(Process* p, Eterm arg1, Eterm arg2);
1604 Eterm erts_mixed_div(Process* p, Eterm arg1, Eterm arg2);
1605 
1606 int erts_int_div_rem(Process* p, Eterm arg1, Eterm arg2, Eterm *q, Eterm *r);
1607 Eterm erts_int_div(Process* p, Eterm arg1, Eterm arg2);
1608 Eterm erts_int_rem(Process* p, Eterm arg1, Eterm arg2);
1609 Eterm erts_bxor(Process* p, Eterm arg1, Eterm arg2);
1610 Eterm erts_bsr(Process* p, Eterm arg1, Eterm arg2);
1611 Eterm erts_bsl(Process* p, Eterm arg1, Eterm arg2);
1612 Eterm erts_bnot(Process* p, Eterm arg);
1613 Eterm erts_bor(Process* p, Eterm arg1, Eterm arg2);
1614 Eterm erts_band(Process* p, Eterm arg1, Eterm arg2);
1615 
1616 Eterm erts_gc_mixed_plus(Process* p, Eterm* reg, Uint live);
1617 Eterm erts_gc_mixed_minus(Process* p, Eterm* reg, Uint live);
1618 Eterm erts_gc_mixed_times(Process* p, Eterm* reg, Uint live);
1619 Eterm erts_gc_mixed_div(Process* p, Eterm* reg, Uint live);
1620 Eterm erts_gc_int_div(Process* p, Eterm* reg, Uint live);
1621 Eterm erts_gc_int_rem(Process* p, Eterm* reg, Uint live);
1622 Eterm erts_gc_band(Process* p, Eterm* reg, Uint live);
1623 Eterm erts_gc_bor(Process* p, Eterm* reg, Uint live);
1624 Eterm erts_gc_bxor(Process* p, Eterm* reg, Uint live);
1625 Eterm erts_gc_bnot(Process* p, Eterm* reg, Uint live);
1626 
1627 Uint erts_current_reductions(Process* current, Process *p);
1628 
1629 int erts_print_system_version(fmtfn_t to, void *arg, Process *c_p);
1630 
1631 int erts_hibernate(Process* c_p, Eterm* reg);
1632 
1633 ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr);
1634 
1635 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1636 
erts_is_literal(Eterm tptr,Eterm * ptr)1637 ERTS_GLB_FORCE_INLINE int erts_is_literal(Eterm tptr, Eterm *ptr)
1638 {
1639     ASSERT(is_boxed(tptr) || is_list(tptr));
1640     ASSERT(ptr == ptr_val(tptr));
1641 
1642 #if defined(ERTS_HAVE_IS_IN_LITERAL_RANGE)
1643     return erts_is_in_literal_range(ptr);
1644 #elif defined(TAG_LITERAL_PTR)
1645     return is_literal_ptr(tptr);
1646 #else
1647 #  error Not able to detect literals...
1648 #endif
1649 
1650 }
1651 
1652 #endif
1653 
1654 Eterm erts_msacc_request(Process *c_p, int action, Eterm *threads);
1655 
1656 /*
1657 ** Call_trace uses this API for the parameter matching functions
1658 */
1659 
1660 #define MatchSetRef(MPSP) 			\
1661 do {						\
1662     if ((MPSP) != NULL) {			\
1663 	erts_refc_inc(&(MPSP)->intern.refc, 1);	\
1664     }						\
1665 } while (0)
1666 
1667 #define MatchSetUnref(MPSP)					\
1668 do {								\
1669     if (((MPSP) != NULL)) {                                     \
1670 	erts_bin_release(MPSP);					\
1671     }								\
1672 } while(0)
1673 
1674 #define MatchSetGetSource(MPSP) erts_match_set_get_source(MPSP)
1675 
1676 extern Binary *erts_match_set_compile(Process *p, Eterm matchexpr, Eterm MFA,
1677                                       Uint *freasonp);
1678 extern void erts_match_set_release_result(Process* p);
1679 ERTS_GLB_INLINE void erts_match_set_release_result_trace(Process* p, Eterm);
1680 
1681 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1682 ERTS_GLB_INLINE
erts_match_set_release_result_trace(Process * p,Eterm pam_result)1683 void erts_match_set_release_result_trace(Process* p, Eterm pam_result)
1684 {
1685     if (is_not_immed(pam_result))
1686         erts_match_set_release_result(p);
1687 }
1688 #endif /* ERTS_GLB_INLINE_INCL_FUNC_DEF */
1689 
1690 enum erts_pam_run_flags {
1691     ERTS_PAM_TMP_RESULT=1,
1692     ERTS_PAM_COPY_RESULT=2,
1693     ERTS_PAM_CONTIGUOUS_TUPLE=4,
1694     ERTS_PAM_IGNORE_TRACE_SILENT=8
1695 };
1696 extern Eterm erts_match_set_run_trace(Process *p,
1697                                       Process *self,
1698                                       Binary *mpsp,
1699                                       Eterm *args, int num_args,
1700                                       enum erts_pam_run_flags in_flags,
1701                                       Uint32 *return_flags);
1702 extern Eterm erts_match_set_get_source(Binary *mpsp);
1703 extern void erts_match_prog_foreach_offheap(Binary *b,
1704 					    void (*)(ErlOffHeap *, void *),
1705 					    void *);
1706 
1707 #define MATCH_SET_RETURN_TRACE    (0x1) /* return trace requested */
1708 #define MATCH_SET_RETURN_TO_TRACE (0x2) /* Misleading name, it is not actually
1709 					   set by the match program, but by the
1710 					   breakpoint functions */
1711 #define MATCH_SET_EXCEPTION_TRACE (0x4) /* exception trace requested */
1712 #define MATCH_SET_RX_TRACE (MATCH_SET_RETURN_TRACE|MATCH_SET_EXCEPTION_TRACE)
1713 
1714 extern erts_driver_t vanilla_driver;
1715 extern erts_driver_t spawn_driver;
1716 extern erts_driver_t forker_driver;
1717 extern erts_driver_t fd_driver;
1718 
1719 int erts_beam_jump_table(void);
1720 
1721 #define DeclareTmpHeap(VariableName,Size,Process) \
1722      Eterm VariableName[Size]
1723 #define DeclareTypedTmpHeap(Type,VariableName,Process)	\
1724      Type VariableName[1]
1725 #define DeclareTmpHeapNoproc(VariableName,Size) \
1726      Eterm VariableName[Size]
1727 #define UseTmpHeap(Size,Proc) /* Nothing */
1728 #define UnUseTmpHeap(Size,Proc) /* Nothing */
1729 #define UseTmpHeapNoproc(Size) /* Nothing */
1730 #define UnUseTmpHeapNoproc(Size) /* Nothing */
1731 
1732 ERTS_GLB_INLINE void dtrace_pid_str(Eterm pid, char *process_buf);
1733 ERTS_GLB_INLINE void dtrace_proc_str(Process *process, char *process_buf);
1734 ERTS_GLB_INLINE void dtrace_port_str(Port *port, char *port_buf);
1735 ERTS_GLB_INLINE void dtrace_fun_decode(Process *process, ErtsCodeMFA *mfa,
1736 				       char *process_buf, char *mfa_buf);
1737 
1738 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1739 
1740 #include "dtrace-wrapper.h"
1741 
1742 ERTS_GLB_INLINE void
dtrace_pid_str(Eterm pid,char * process_buf)1743 dtrace_pid_str(Eterm pid, char *process_buf)
1744 {
1745     if (is_pid(pid))
1746         erts_snprintf(process_buf, DTRACE_TERM_BUF_SIZE, "<%lu.%lu.%lu>",
1747                       pid_channel_no(pid),
1748                       pid_number(pid),
1749                       pid_serial(pid));
1750     else if (is_port(pid))
1751         erts_snprintf(process_buf, DTRACE_TERM_BUF_SIZE, "#Port<%lu.%b64u>",
1752                       port_channel_no(pid),
1753                       port_number(pid));
1754 }
1755 
1756 ERTS_GLB_INLINE void
dtrace_proc_str(Process * process,char * process_buf)1757 dtrace_proc_str(Process *process, char *process_buf)
1758 {
1759     dtrace_pid_str(process->common.id, process_buf);
1760 }
1761 
1762 ERTS_GLB_INLINE void
dtrace_port_str(Port * port,char * port_buf)1763 dtrace_port_str(Port *port, char *port_buf)
1764 {
1765     dtrace_pid_str(port->common.id, port_buf);
1766 }
1767 
1768 ERTS_GLB_INLINE void
dtrace_fun_decode(Process * process,ErtsCodeMFA * mfa,char * process_buf,char * mfa_buf)1769 dtrace_fun_decode(Process *process, ErtsCodeMFA *mfa,
1770                   char *process_buf, char *mfa_buf)
1771 {
1772     if (process_buf) {
1773         dtrace_proc_str(process, process_buf);
1774     }
1775 
1776     erts_snprintf(mfa_buf, DTRACE_TERM_BUF_SIZE, "%T:%T/%d",
1777                   mfa->module, mfa->function, mfa->arity);
1778 }
1779 
1780 #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
1781 
1782 #endif /* !__GLOBAL_H__ */
1783