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 __SYS_H__
22 #define __SYS_H__
23 
24 #define ERTS_SUPPORT_OLD_RECV_MARK_INSTRS
25 
26 #if !defined(__GNUC__) || defined(__e2k__)
27 #  define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) 0
28 #elif !defined(__GNUC_MINOR__)
29 #  define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
30   ((__GNUC__ << 24) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
31 #elif !defined(__GNUC_PATCHLEVEL__)
32 #  define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
33   (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12)) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
34 #else
35 #  define ERTS_AT_LEAST_GCC_VSN__(MAJ, MIN, PL) \
36   (((__GNUC__ << 24) | (__GNUC_MINOR__ << 12) | __GNUC_PATCHLEVEL__) >= (((MAJ) << 24) | ((MIN) << 12) | (PL)))
37 #endif
38 
39 
40 #ifdef ERTS_INLINE
41 #  ifndef ERTS_CAN_INLINE
42 #    define ERTS_CAN_INLINE 1
43 #  endif
44 #else
45 #  if defined(__GNUC__)
46 #    define ERTS_CAN_INLINE 1
47 #    define ERTS_INLINE __inline__
48 #  elif defined(__WIN32__)
49 #    define ERTS_CAN_INLINE 1
50 #    define ERTS_INLINE __inline
51 #  else
52 #    define ERTS_CAN_INLINE 0
53 #    define ERTS_INLINE
54 #  endif
55 #endif
56 
57 #ifndef ERTS_FORCE_INLINE
58 #  if ERTS_AT_LEAST_GCC_VSN__(3,1,1)
59 #    define ERTS_FORCE_INLINE __inline__ __attribute__((__always_inline__))
60 #  elif defined(__WIN32__)
61 #    define ERTS_FORCE_INLINE __forceinline
62 #  endif
63 #  ifndef ERTS_FORCE_INLINE
64 #    define ERTS_FORCE_INLINE ERTS_INLINE
65 #  endif
66 #endif
67 
68 #ifndef ERTS_NOINLINE
69 #  if ERTS_AT_LEAST_GCC_VSN__(3,1,1)
70 #    define ERTS_NOINLINE __attribute__((__noinline__))
71 #  else
72 #    define ERTS_NOINLINE
73 #  endif
74 #endif
75 
76 #if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
77 #  undef ERTS_CAN_INLINE
78 #  define ERTS_CAN_INLINE 0
79 #  undef ERTS_INLINE
80 #  define ERTS_INLINE
81 #endif
82 
83 #if ERTS_CAN_INLINE
84 #define ERTS_GLB_FORCE_INLINE static ERTS_FORCE_INLINE
85 #define ERTS_GLB_INLINE static ERTS_INLINE
86 #else
87 #define ERTS_GLB_FORCE_INLINE
88 #define ERTS_GLB_INLINE
89 #endif
90 
91 #if (ERTS_CAN_INLINE || defined(ERTS_DO_INCL_GLB_INLINE_FUNC_DEF))
92 #  define ERTS_GLB_INLINE_INCL_FUNC_DEF 1
93 #else
94 #  define ERTS_GLB_INLINE_INCL_FUNC_DEF 0
95 #endif
96 
97 #ifdef __GNUC__
98 #  define ERTS_NOINLINE __attribute__((__noinline__))
99 #else
100 #  define ERTS_NOINLINE
101 #endif
102 
103 #define ERTS_I64_LITERAL(X) X##LL
104 
105 #define ErtsInArea(ptr,start,nbytes) \
106     ((UWord)((char*)(ptr) - (char*)(start)) < (nbytes))
107 
108 #define ErtsContainerStruct(ptr, type, member) \
109     ((type *)((char *)(1 ? (ptr) : &((type *)0)->member) - offsetof(type, member)))
110 
111 /* Use this variant when the member is an array */
112 #define ErtsContainerStruct_(ptr, type, memberv) \
113     ((type *)((char *)(1 ? (ptr) : ((type *)0)->memberv) - offsetof(type, memberv)))
114 
115 #define ErtsSizeofMember(type, member) sizeof(((type *)0)->member)
116 
117 #if defined (__WIN32__)
118 #  include "erl_win_sys.h"
119 #else
120 #  include "erl_unix_sys.h"
121 #ifndef UNIX
122 #  define UNIX 1
123 #endif
124 #endif
125 
126 /*
127  * Test for clang's convenient __has_builtin feature checking macro.
128  */
129 #ifndef __has_builtin
130   #define __has_builtin(x) 0
131 #endif
132 
133 /*
134  * Define HAVE_OVERFLOW_CHECK_BUILTINS if the overflow checking arithmetic
135  * builtins are available.
136  */
137 #if ERTS_AT_LEAST_GCC_VSN__(5, 1, 0)
138 #  define HAVE_OVERFLOW_CHECK_BUILTINS 1
139 #elif __has_builtin(__builtin_mul_overflow)
140 #  define HAVE_OVERFLOW_CHECK_BUILTINS 1
141 #endif
142 
143 #include "erl_misc_utils.h"
144 
145 /*
146  * To allow building of Universal Binaries for Mac OS X,
147  * we must not depend on the endian detected by the configure script.
148  */
149 #if defined(__APPLE__)
150 #  if defined(__BIG_ENDIAN__) && !defined(WORDS_BIGENDIAN)
151 #    define WORDS_BIGENDIAN 1
152 #  elif !defined(__BIG_ENDIAN__) && defined(WORDS_BIGENDIAN)
153 #    undef WORDS_BIGENDIAN
154 #  endif
155 #endif
156 
157 /*
158  * Make sure we have a type for FD's (used by erl_check_io)
159  */
160 
161 #ifndef ERTS_SYS_FD_TYPE
162 #define ERTS_SYS_FD_INVALID ((ErtsSysFdType) -1)
163 typedef int ErtsSysFdType;
164 #else
165 #ifndef ERTS_SYS_FD_INVALID
166 # error missing ERTS_SYS_FD_INVALID
167 #endif
168 typedef ERTS_SYS_FD_TYPE ErtsSysFdType;
169 #endif
170 
171 #if ERTS_AT_LEAST_GCC_VSN__(2, 96, 0)
172 #  define ERTS_LIKELY(BOOL)   __builtin_expect((BOOL), !0)
173 #  define ERTS_UNLIKELY(BOOL) __builtin_expect((BOOL), 0)
174 #else
175 #  define ERTS_LIKELY(BOOL)   (BOOL)
176 #  define ERTS_UNLIKELY(BOOL) (BOOL)
177 #endif
178 
179 /* AIX doesn't like this and claims section conflicts */
180 #if ERTS_AT_LEAST_GCC_VSN__(2, 96, 0) && !defined(_AIX)
181 #if (defined(__APPLE__) && defined(__MACH__)) || defined(__DARWIN__)
182 #  define ERTS_WRITE_UNLIKELY(X) X __attribute__ ((section ("__DATA,ERTS_LOW_WRITE") ))
183 #else
184 #  define ERTS_WRITE_UNLIKELY(X) X __attribute__ ((section ("ERTS_LOW_WRITE") ))
185 #endif
186 #else
187 #  define ERTS_WRITE_UNLIKELY(X) X
188 #endif
189 
190 /* clang may have too low __GNUC__ versions but can handle it */
191 #ifdef __GNUC__
192 #  if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 5) || defined(__clang__)
193 #    define ERTS_DECLARE_DUMMY(X) X __attribute__ ((unused))
194 #  else
195 #    define ERTS_DECLARE_DUMMY(X) X
196 #  endif
197 #else
198 #  define ERTS_DECLARE_DUMMY(X) X
199 #endif
200 
201 #if !defined(__func__)
202 #  if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L
203 #    if !defined(__GNUC__) ||  __GNUC__ < 2
204 #      define __func__ "[unknown_function]"
205 #    else
206 #      define __func__ __FUNCTION__
207 #    endif
208 #  endif
209 #endif
210 
211 #define ERTS_MK_VSN_INT(Major, Minor, Build) \
212     ((((Major) & 0x3ff) << 20) | (((Minor) & 0x3ff) << 10) | ((Build) & 0x3ff))
213 
214 #ifndef ERTS_EXIT_AFTER_DUMP
215 #  define ERTS_EXIT_AFTER_DUMP exit
216 #endif
217 
218 /* In VC++, noreturn is a declspec that has to be before the types,
219  * but in GNUC it is an attribute to be placed between return type
220  * and function name, hence __decl_noreturn <types> __noreturn <function name>
221  *
222  * at some platforms (e.g. Android) __noreturn is defined at sys/cdef.h
223  */
224 #if __GNUC__
225 #  define __decl_noreturn
226 #  ifndef __noreturn
227 #     define __noreturn __attribute__((noreturn))
228 #  endif
229 #else
230 #  if defined(__WIN32__) && defined(_MSC_VER)
231 #    define __noreturn
232 #    define __decl_noreturn __declspec(noreturn)
233 #  else
234 #    define __noreturn
235 #    define __decl_noreturn
236 #  endif
237 #endif
238 
239 #define ERTS_ASSERT(e) \
240     ((void) ((e) ? 1 : (erl_assert_error(#e, __func__, __FILE__, __LINE__), 0)))
241 
242 __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *func,
243 						 const char* file, int line);
244 
245 #ifdef DEBUG
246 #  define ASSERT(e) ERTS_ASSERT(e)
247 #else
248 #  define ASSERT(e) ((void) 1)
249 #endif
250 
251 /* ERTS_UNDEF can be used to silence false warnings about
252  * "variable may be used uninitialized" while keeping the variable
253  * marked as undefined by valgrind.
254  */
255 #ifdef VALGRIND
256 #  define ERTS_UNDEF(V,I)
257 #else
258 #  define ERTS_UNDEF(V,I) V = I
259 #endif
260 
261 /*
262  * ERTS_GCC_DIAG_ON and ERTS_GCC_DIAG_OFF can be used to temporarly
263  * disable a gcc or clang warning in a file.
264  *
265  * Example:
266  * GCC_DIAG_OFF(unused-function)
267  * static int test(){ return 0;}
268  * GCC_DIAG_ON(unused-function)
269  *
270  * These macros were orginally authored by Jonathan Wakely and has
271  * been modified by Patrick Horgan.
272  *
273  * Source: http://dbp-consulting.com/tutorials/SuppressingGCCWarnings.html
274  *
275  */
276 #if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 402
277 #define ERTS_GCC_DIAG_STR(s) #s
278 #define ERTS_GCC_DIAG_JOINSTR(x,y) ERTS_GCC_DIAG_STR(x ## y)
279 # define ERTS_GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
280 # define ERTS_GCC_DIAG_PRAGMA(x) ERTS_GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
281 # if ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
282 #  define ERTS_GCC_DIAG_OFF(x) ERTS_GCC_DIAG_PRAGMA(push) \
283       ERTS_GCC_DIAG_PRAGMA(ignored ERTS_GCC_DIAG_JOINSTR(-W,x))
284 #  define ERTS_GCC_DIAG_ON(x) ERTS_GCC_DIAG_PRAGMA(pop)
285 # else
286 #  define ERTS_GCC_DIAG_OFF(x) ERTS_GCC_DIAG_PRAGMA(ignored ERTS_GCC_DIAG_JOINSTR(-W,x))
287 #  define ERTS_GCC_DIAG_ON(x)  ERTS_GCC_DIAG_PRAGMA(warning ERTS_GCC_DIAG_JOINSTR(-W,x))
288 # endif
289 #else
290 # define ERTS_GCC_DIAG_OFF(x)
291 # define ERTS_GCC_DIAG_ON(x)
292 #endif
293 
294 /*
295  * Compile time assert
296  * (the actual compiler error msg can be a bit confusing)
297  */
298 #if ERTS_AT_LEAST_GCC_VSN__(3,1,1) && !defined __cplusplus
299 # define ERTS_CT_ASSERT(e) \
300     do { \
301 	enum { compile_time_assert__ = __builtin_choose_expr((e),0,(void)0) }; \
302     } while(0)
303 #else
304 # define ERTS_CT_ASSERT(e) \
305     do { \
306         enum { compile_time_assert__ = 1/((int)(e)) };  \
307     } while (0)
308 #endif
309 
310 /*
311  * Microsoft C/C++: We certainly want to use stdarg.h and prototypes.
312  * But MSC doesn't define __STDC__, unless we compile with the -Za
313  * flag (strict ANSI C, no Microsoft extension).  Compiling with -Za
314  * doesn't work: some Microsoft headers fail to compile...
315  *
316  * Solution: Test if __STDC__ or _MSC_VER is defined.
317  *
318  * Note: Simply defining __STDC__ doesn't work, as some Microsoft
319  * headers will fail to compile!
320  */
321 
322 #include <stdarg.h>
323 
324 /* This isn't sys-dependent, but putting it here benefits sys.c and drivers
325    - allow use of 'const' regardless of compiler */
326 
327 #if !defined(__STDC__) && !defined(_MSC_VER)
328 #  define const
329 #endif
330 
331 #undef __deprecated
332 #if ERTS_AT_LEAST_GCC_VSN__(3, 0, 0)
333 #  define __deprecated __attribute__((deprecated))
334 #else
335 #  define __deprecated
336 #endif
337 #if ERTS_AT_LEAST_GCC_VSN__(3, 0, 4)
338 #  define erts_align_attribute(SZ) __attribute__ ((aligned (SZ)))
339 #else
340 #  define erts_align_attribute(SZ)
341 #endif
342 
343 /*
344 ** Data types:
345 **
346 ** Eterm: A tagged erlang term (possibly 64 bits)
347 ** BeamInstr: A beam code instruction unit, possibly larger than Eterm, not smaller.
348 ** Uint:  An unsigned integer exactly as large as an Eterm.
349 ** Sint:  A signed integer exactly as large as an eterm and therefor large
350 **        enough to hold the return value of the signed_val() macro.
351 ** UWord: An unsigned integer at least as large as a void * and also as large
352 **          or larger than an Eterm
353 ** SWord: A signed integer at least as large as a void * and also as large
354 **          or larger than an Eterm
355 ** Uint32: An unsigned integer of 32 bits exactly
356 ** Sint32: A signed integer of 32 bits exactly
357 ** Uint16: An unsigned integer of 16 bits exactly
358 ** Sint16: A signed integer of 16 bits exactly.
359 */
360 
361 #if !((SIZEOF_VOID_P >= 4) && (SIZEOF_VOID_P == SIZEOF_SIZE_T) \
362       && ((SIZEOF_VOID_P == SIZEOF_INT) || (SIZEOF_VOID_P == SIZEOF_LONG) || \
363           (SIZEOF_VOID_P == SIZEOF_LONG_LONG)))
364 #error Cannot handle this combination of int/long/void*/size_t sizes
365 #endif
366 
367 #if SIZEOF_VOID_P == 8
368 #undef  ARCH_32
369 #define ARCH_64
370 #define ERTS_SIZEOF_TERM 8
371 #elif SIZEOF_VOID_P == 4
372 #define ARCH_32
373 #undef  ARCH_64
374 #define ERTS_SIZEOF_TERM 4
375 #else
376 #error Neither 32 nor 64 bit architecture
377 #endif
378 
379 #if SIZEOF_VOID_P != SIZEOF_SIZE_T
380 #error sizeof(void*) != sizeof(size_t)
381 #endif
382 
383 #if SIZEOF_VOID_P == SIZEOF_LONG
384 typedef unsigned long Eterm erts_align_attribute(sizeof(long));
385 typedef unsigned long Uint  erts_align_attribute(sizeof(long));
386 typedef long          Sint  erts_align_attribute(sizeof(long));
387 #define SWORD_CONSTANT(Const) Const##L
388 #define UWORD_CONSTANT(Const) Const##UL
389 #define ERTS_UWORD_MAX ULONG_MAX
390 #define ERTS_SWORD_MAX LONG_MAX
391 #define ERTS_SWORD_MIN LONG_MIN
392 #define ERTS_SIZEOF_ETERM SIZEOF_LONG
393 #define ErtsStrToSint strtol
394 #elif SIZEOF_VOID_P == SIZEOF_INT
395 typedef unsigned int Eterm erts_align_attribute(sizeof(int));
396 typedef unsigned int Uint  erts_align_attribute(sizeof(int));
397 typedef int          Sint  erts_align_attribute(sizeof(int));
398 #define SWORD_CONSTANT(Const) Const
399 #define UWORD_CONSTANT(Const) Const##U
400 #define ERTS_UWORD_MAX UINT_MAX
401 #define ERTS_SWORD_MAX INT_MAX
402 #define ERTS_SWORD_MIN INT_MIN
403 #define ERTS_SIZEOF_ETERM SIZEOF_INT
404 #define ErtsStrToSint strtol
405 #elif SIZEOF_VOID_P == SIZEOF_LONG_LONG
406 typedef unsigned long long Eterm erts_align_attribute(sizeof(long long));
407 typedef unsigned long long Uint  erts_align_attribute(sizeof(long long));
408 typedef long long          Sint  erts_align_attribute(sizeof(long long));
409 #define SWORD_CONSTANT(Const) Const##LL
410 #define UWORD_CONSTANT(Const) Const##ULL
411 #define ERTS_UWORD_MAX ULLONG_MAX
412 #define ERTS_SWORD_MAX LLONG_MAX
413 #define ERTS_SWORD_MIN LLONG_MIN
414 #define ERTS_SIZEOF_ETERM SIZEOF_LONG_LONG
415 #if defined(__WIN32__)
416 #define ErtsStrToSint _strtoi64
417 #else
418 #define ErtsStrToSint strtoll
419 #endif
420 #else
421 #error Found no appropriate type to use for 'Eterm', 'Uint' and 'Sint'
422 #endif
423 
424 typedef Uint UWord;
425 typedef Sint SWord;
426 #define ERTS_UINT_MAX ERTS_UWORD_MAX
427 
428 typedef const void *ErtsCodePtr;
429 typedef UWord BeamInstr;
430 
431 #ifndef HAVE_INT64
432 #  if SIZEOF_LONG == 8
433 #    define HAVE_INT64 1
434 typedef unsigned long Uint64;
435 typedef long          Sint64;
436 #    define ErtsStrToSint64 strtol
437 #  elif SIZEOF_LONG_LONG == 8
438 #    define HAVE_INT64 1
439 typedef unsigned long long Uint64;
440 typedef long long          Sint64;
441 #    define ErtsStrToSint64 strtoll
442 #  else
443 #    error "No 64-bit integer type found"
444 #  endif
445 #endif
446 
447 #ifndef ERTS_UINT64_MAX
448 #  define ERTS_UINT64_MAX (~((Uint64) 0))
449 #endif
450 #ifndef ERTS_SINT64_MAX
451 #  define ERTS_SINT64_MAX ((Sint64) ((((Uint64) 1) << 63)-1))
452 #endif
453 #ifndef ERTS_SINT64_MIN
454 #  define ERTS_SINT64_MIN ((Sint64) ((((Uint64) 1) << 63)))
455 #endif
456 
457 #if SIZEOF_LONG == 4
458 typedef unsigned long Uint32;
459 typedef long          Sint32;
460 #elif SIZEOF_INT == 4
461 typedef unsigned int Uint32;
462 typedef int          Sint32;
463 #else
464 #error Found no appropriate type to use for 'Uint32' and 'Sint32'
465 #endif
466 
467 #ifndef ERTS_UINT32_MAX
468 #  define ERTS_UINT32_MAX (~((Uint32) 0))
469 #endif
470 #ifndef ERTS_SINT32_MAX
471 #  define ERTS_SINT32_MAX ((Sint32) ((((Uint32) 1) << 31)-1))
472 #endif
473 #ifndef ERTS_SINT32_MIN
474 #  define ERTS_SINT32_MIN ((Sint32) ((((Uint32) 1) << 31)))
475 #endif
476 
477 #if SIZEOF_INT == 2
478 typedef unsigned int Uint16;
479 typedef int          Sint16;
480 #elif SIZEOF_SHORT == 2
481 typedef unsigned short Uint16;
482 typedef short          Sint16;
483 #else
484 #error Found no appropriate type to use for 'Uint16' and 'Sint16'
485 #endif
486 
487 #ifndef ERTS_UINT16_MAX
488 #  define ERTS_UINT16_MAX (~((Uint16) 0))
489 #endif
490 #ifndef ERTS_SINT16_MAX
491 #  define ERTS_SINT16_MAX ((Sint16) ((((Uint16) 1) << 15)-1))
492 #endif
493 #ifndef ERTS_SINT16_MIN
494 #  define ERTS_SINT16_MIN ((Sint16) ((((Uint16) 1) << 15)))
495 #endif
496 
497 #if CHAR_BIT == 8
498 typedef unsigned char byte;
499 #else
500 #error Found no appropriate type to use for 'byte'
501 #endif
502 
503 #if defined(ARCH_64) && !HAVE_INT64
504 #error 64-bit architecture, but no appropriate type to use for Uint64 and Sint64 found
505 #endif
506 
507 #ifdef WORDS_BIGENDIAN
508 #  define ERTS_HUINT_HVAL_HIGH 0
509 #  define ERTS_HUINT_HVAL_LOW 1
510 #else
511 #  define ERTS_HUINT_HVAL_HIGH 1
512 #  define ERTS_HUINT_HVAL_LOW 0
513 #endif
514 #if ERTS_SIZEOF_TERM == 8
515 typedef union {
516     Uint val;
517     Uint32 hval[2];
518 } HUint;
519 #elif ERTS_SIZEOF_TERM == 4
520 typedef union {
521     Uint val;
522     Uint16 hval[2];
523 } HUint;
524 #else
525 #error "Unsupported size of term"
526 #endif
527 
528 #  define ERTS_EXTRA_DATA_ALIGN_SZ(X) \
529     (((size_t) 8) - (((size_t) (X)) & ((size_t) 7)))
530 
531 #include "erl_lock_check.h"
532 
533 /* needed by erl_threads.h */
534 int erts_send_warning_to_logger_str_nogl(char *);
535 
536 #include "erl_threads.h"
537 
538 #ifdef ERTS_WANT_BREAK_HANDLING
539 extern erts_atomic32_t erts_break_requested;
540 #    define ERTS_BREAK_REQUESTED \
541   ((int) erts_atomic32_read_nob(&erts_break_requested))
542 void erts_do_break_handling(void);
543 #endif
544 
545 
546 extern erts_atomic32_t erts_writing_erl_crash_dump;
547 extern erts_tsd_key_t erts_is_crash_dumping_key;
548 #define ERTS_SOMEONE_IS_CRASH_DUMPING \
549   ((int) erts_atomic32_read_mb(&erts_writing_erl_crash_dump))
550 #define ERTS_IS_CRASH_DUMPING \
551   ((int) (SWord) erts_tsd_get(erts_is_crash_dumping_key))
552 
553 /* Deal with memcpy() vs bcopy() etc. We want to use the mem*() functions,
554    but be able to fall back on bcopy() etc on systems that don't have
555    mem*(), but this doesn't work to well with memset()/bzero() - thus the
556    memzero() macro.
557 */
558 
559 /* xxxP */
560 #if defined(USE_BCOPY)
561 #  define memcpy(a, b, c) bcopy((b), (a), (c))
562 #  define memcmp(a, b, c) bcmp((a), (b), (c))
563 #  define memzero(buf, len) bzero((buf), (len))
564 #else
565 #  define memzero(buf, len) memset((buf), '\0', (len))
566 #endif
567 
568 /* Stuff that is useful for port programs, drivers, etc */
569 
570 #ifdef ISC32			/* Too much for the Makefile... */
571 #  define signal	sigset
572 #  define NO_ASINH
573 #  define NO_ACOSH
574 #  define NO_ATANH
575 #  define NO_FTRUNCATE
576 #  define SIG_SIGHOLD
577 #  define _POSIX_SOURCE
578 #  define _XOPEN_SOURCE
579 #endif
580 
581 #ifdef QNX			/* Too much for the Makefile... */
582 #  define SYS_SELECT_H
583 #  define NO_ERF
584 #  define NO_ERFC
585 /* This definition doesn't take NaN into account, but matherr() gets those */
586 #  define isfinite(x) (fabs(x) != HUGE_VAL)
587 #  define USE_MATHERR
588 #  define HAVE_FINITE
589 #endif
590 
591 
592 #ifdef WANT_NONBLOCKING	    /* must define this to pull in fcntl.h/ioctl.h */
593 
594 /* This is really a mess... We used to use fcntl O_NDELAY, but that seems
595    to only work on SunOS 4 - in particular, on SysV-based systems
596    (including Solaris 2), it does set non-blocking mode, but causes
597    read() to return 0!!  fcntl O_NONBLOCK is specified by POSIX, and
598    seems to work on most systems, with the notable exception of AIX,
599    where the old ioctl FIONBIO is the *only* one that will set a *socket*
600    in non-blocking mode - and ioctl FIONBIO on AIX *doesn't* work for
601    pipes or ttys (O_NONBLOCK does)!!! For now, we'll use FIONBIO for AIX. */
602 
603 #  ifdef __WIN32__
604 
605 static unsigned long zero_value = 0, one_value = 1;
606 #    define SET_BLOCKING(fd)	{ if (ioctlsocket((fd), FIONBIO, &zero_value) != 0) fprintf(stderr, "Error setting socket to non-blocking: %d\n", WSAGetLastError()); }
607 #    define SET_NONBLOCKING(fd)	ioctlsocket((fd), FIONBIO, &one_value)
608 
609 #  else
610 #    ifdef NB_FIONBIO		/* Old BSD */
611 #      include <sys/ioctl.h>
612   static const int zero_value = 0, one_value = 1;
613 #      define SET_BLOCKING(fd)         ioctl((fd), FIONBIO, &zero_value)
614 #      define SET_NONBLOCKING(fd)      ioctl((fd), FIONBIO, &one_value)
615 #      define ERRNO_BLOCK EWOULDBLOCK
616 #    else /* !NB_FIONBIO */
617 #      include <fcntl.h>
618 #      ifdef NB_O_NDELAY               /* Nothing needs this? */
619 #        define NB_FLAG O_NDELAY
620 #        ifndef ERRNO_BLOCK            /* allow override (e.g. EAGAIN) via Makefile */
621 #          define ERRNO_BLOCK EWOULDBLOCK
622 #        endif
623 #      else  /* !NB_O_NDELAY */	/* The True Way - POSIX!:-) */
624 #        define NB_FLAG O_NONBLOCK
625 #        define ERRNO_BLOCK EAGAIN
626 #      endif /* !NB_O_NDELAY */
627 #      define SET_BLOCKING(fd)         fcntl((fd), F_SETFL, \
628                                            fcntl((fd), F_GETFL, 0) & ~NB_FLAG)
629 #      define SET_NONBLOCKING(fd)      fcntl((fd), F_SETFL, \
630                                            fcntl((fd), F_GETFL, 0) | NB_FLAG)
631 #    endif /* !NB_FIONBIO */
632 #  endif /* !__WIN32__ */
633 #endif /* WANT_NONBLOCKING */
634 
635 __decl_noreturn void __noreturn erts_exit(int n, const char*, ...);
636 
637 /* Some special erts_exit() codes: */
638 #define ERTS_INTR_EXIT	-1		/* called from signal handler */
639 #define ERTS_ABORT_EXIT	-2	        /* no crash dump; only abort() */
640 #define ERTS_DUMP_EXIT	-3              /* crash dump; then exit() */
641 #define ERTS_ERROR_EXIT	-4              /* crash dump; then abort() */
642 
643 #define ERTS_INTERNAL_ERROR(What) \
644     erts_exit(ERTS_ABORT_EXIT, "%s:%d:%s(): Internal error: %s\n", \
645 	     __FILE__, __LINE__, __func__, What)
646 
647 UWord erts_sys_get_page_size(void);
648 
649 /* Size of misc memory allocated from system dependent code */
650 Uint erts_sys_misc_mem_sz(void);
651 
652 /* print stuff is declared here instead of in global.h, so sys stuff won't
653    have to include global.h */
654 #include "erl_printf.h"
655 
656 /* Io constants to erts_print and erts_putc */
657 #define ERTS_PRINT_STDERR	((fmtfn_t)0)
658 #define ERTS_PRINT_STDOUT	((fmtfn_t)1)
659 #define ERTS_PRINT_FILE		((fmtfn_t)2)
660 #define ERTS_PRINT_SBUF		((fmtfn_t)3)
661 #define ERTS_PRINT_SNBUF	((fmtfn_t)4)
662 #define ERTS_PRINT_DSBUF	((fmtfn_t)5)
663 #define ERTS_PRINT_FD           ((fmtfn_t)6)
664 
665 typedef struct {
666     char *buf;
667     size_t size;
668 } erts_print_sn_buf;
669 
670 int erts_print(fmtfn_t to, void *arg, char *format, ...);	/* in utils.c */
671 int erts_putc(fmtfn_t to, void *arg, char);			/* in utils.c */
672 
673 /* logger stuff is declared here instead of in global.h, so sys files
674    won't have to include global.h */
675 
676 erts_dsprintf_buf_t *erts_create_logger_dsbuf(void);
677 int erts_send_info_to_logger(Eterm, erts_dsprintf_buf_t *);
678 int erts_send_warning_to_logger(Eterm, erts_dsprintf_buf_t *);
679 int erts_send_error_to_logger(Eterm, erts_dsprintf_buf_t *);
680 int erts_send_error_term_to_logger(Eterm, erts_dsprintf_buf_t *, Eterm);
681 int erts_send_info_to_logger_str(Eterm, char *);
682 int erts_send_warning_to_logger_str(Eterm, char *);
683 int erts_send_error_to_logger_str(Eterm, char *);
684 int erts_send_info_to_logger_nogl(erts_dsprintf_buf_t *);
685 int erts_send_warning_to_logger_nogl(erts_dsprintf_buf_t *);
686 int erts_send_error_to_logger_nogl(erts_dsprintf_buf_t *);
687 int erts_send_info_to_logger_str_nogl(char *);
688 /* needed by erl_threads.h (declared above)
689    int erts_send_warning_to_logger_str_nogl(char *); */
690 int erts_send_error_to_logger_str_nogl(char *);
691 
692 typedef struct preload {
693     char *name;			/* Name of module */
694     int  size;			/* Size of code */
695     unsigned char* code;	/* Code pointer */
696 } Preload;
697 
698 /*
699  * ErtsTracer is either NIL, 'true' or [Mod | State]
700  *
701  * If set to NIL, it means no tracer.
702  * If set to 'true' it means the current process' tracer.
703  * If set to [Mod | State], there is a tracer.
704  *  See erts_tracer_update for more details
705  */
706 typedef Eterm ErtsTracer;
707 
708 
709 /*
710  * This structure contains the rb tree for the erlang osenv copy
711  * see erl_osenv.h for more details.
712  */
713 typedef struct __erts_osenv_t {
714     struct __env_rbtnode_t *tree;
715     int variable_count;
716     int content_size;
717 } erts_osenv_t;
718 
719 extern char *erts_default_arg0;
720 
721 extern char os_type[];
722 
723 typedef struct {
724     int have_os_monotonic_time;
725     int have_corrected_os_monotonic_time;
726     ErtsMonotonicTime os_monotonic_time_unit;
727     ErtsMonotonicTime sys_clock_resolution;
728     struct {
729 	Uint64 resolution;
730 	char *func;
731 	char *clock_id;
732 	int locked_use;
733 	int extended;
734     } os_monotonic_time_info;
735     struct {
736 	Uint64 resolution;
737 	char *func;
738 	char *clock_id;
739 	int locked_use;
740     } os_system_time_info;
741 } ErtsSysInitTimeResult;
742 
743 #define ERTS_SYS_INIT_TIME_RESULT_INITER \
744     {0, 0, (ErtsMonotonicTime) -1, (ErtsMonotonicTime) 1}
745 
746 extern void erts_init_sys_time_sup(void);
747 extern void sys_init_time(ErtsSysInitTimeResult *);
748 extern void erts_late_sys_init_time(void);
749 extern void erts_deliver_time(void);
750 extern void erts_time_remaining(SysTimeval *);
751 extern void erts_sys_init_float(void);
752 
753 /* Dynamic library/driver loading */
754 typedef struct {
755     char* str;
756 }ErtsSysDdllError;
757 #define ERTS_SYS_DDLL_ERROR_INIT {NULL}
758 extern void erts_sys_ddll_free_error(ErtsSysDdllError*);
759 extern void erl_sys_ddll_init(void); /* to initialize mutexes etc */
760 extern int erts_sys_ddll_open(const char *path, void **handle, ErtsSysDdllError*);
761 extern int erts_sys_ddll_open_noext(char *path, void **handle, ErtsSysDdllError*);
762 extern int erts_sys_ddll_load_driver_init(void *handle, void **function);
763 extern int erts_sys_ddll_load_nif_init(void *handle, void **function,ErtsSysDdllError*);
764 extern int erts_sys_ddll_close2(void *handle, ErtsSysDdllError*);
765 #define erts_sys_ddll_close(H) erts_sys_ddll_close2(H,NULL)
766 extern void *erts_sys_ddll_call_init(void *function);
767 extern void *erts_sys_ddll_call_nif_init(void *function);
768 extern int erts_sys_ddll_sym2(void *handle, const char *name, void **function, ErtsSysDdllError*);
769 #define erts_sys_ddll_sym(H,N,F) erts_sys_ddll_sym2(H,N,F,NULL)
770 extern char *erts_sys_ddll_error(int code);
771 
772 
773 
774 /*
775  * System interfaces for startup.
776  */
777 void erts_sys_main_thread(void);
778 
779 extern int erts_sys_prepare_crash_dump(int secs);
780 extern void erts_sys_pre_init(void);
781 
782 /* Platform-specific scheduler initialization, e.g. signal stack swapping. */
783 extern void erts_sys_scheduler_init(void);
784 
785 extern void erl_sys_init(void);
786 extern void erl_sys_late_init(void);
787 extern void erl_sys_args(int *argc, char **argv);
788 extern void erl_sys_schedule(int);
789 void sys_tty_reset(int);
790 
791 int sys_max_files(void);
792 void sys_init_io(void);
793 Preload* sys_preloaded(void);
794 unsigned char* sys_preload_begin(Preload*);
795 void sys_preload_end(Preload*);
796 int sys_get_key(int);
797 void get_time(int *hour, int *minute, int *second);
798 void get_date(int *year, int *month, int *day);
799 void get_localtime(int *year, int *month, int *day,
800 		   int *hour, int *minute, int *second);
801 void get_universaltime(int *year, int *month, int *day,
802 		       int *hour, int *minute, int *second);
803 int seconds_to_univ(Sint64 seconds,
804 		    Sint *year, Sint *month, Sint *day,
805 		    Sint *hour, Sint *minute, Sint *second);
806 int univ_to_seconds(Sint year, Sint month, Sint day,
807 		    Sint hour, Sint minute, Sint second,
808 		    Sint64* seconds);
809 int univ_to_local(
810     Sint *year, Sint *month, Sint *day,
811 		  Sint *hour, Sint *minute, Sint *second);
812 int local_to_univ(Sint *year, Sint *month, Sint *day,
813 		  Sint *hour, Sint *minute, Sint *second, int isdst);
814 void get_now(Uint*, Uint*, Uint*);
815 struct ErtsSchedulerData_;
816 ErtsMonotonicTime erts_get_monotonic_time(struct ErtsSchedulerData_ *);
817 ErtsMonotonicTime erts_get_time_offset(void);
818 void
819 erts_make_timestamp_value(Uint* megasec, Uint* sec, Uint* microsec,
820 			  ErtsMonotonicTime mtime, ErtsMonotonicTime offset);
821 void get_sys_now(Uint*, Uint*, Uint*);
822 void set_break_quit(void (*)(void), void (*)(void));
823 
824 void os_flavor(char*, unsigned);
825 void os_version(int*, int*, int*);
826 
827 #define HAVE_ERTS_CHECK_IO_DEBUG
828 typedef struct {
829     int no_used_fds;
830     int no_driver_select_structs;
831     int no_enif_select_structs;
832 } ErtsCheckIoDebugInfo;
833 int erts_check_io_debug(ErtsCheckIoDebugInfo *ip);
834 
835 int erts_sys_is_area_readable(char *start, char *stop);
836 
837 /* xxxP */
838 #define SYS_DEFAULT_FLOAT_DECIMALS 20
839 void init_sys_float(void);
840 int sys_chars_to_double(char*, double*);
841 int sys_double_to_chars(double, char*, size_t);
842 int sys_double_to_chars_ext(double, char*, size_t, size_t);
843 int sys_double_to_chars_fast(double, char*, int, int, int);
844 void sys_get_pid(char *, size_t);
845 
846 /* erl_drv_get/putenv have been implicitly 8-bit for so long that we can't
847  * change them without breaking things on Windows. Their return values are
848  * identical to erts_osenv_get/putenv */
849 int erts_sys_explicit_8bit_getenv(char *key, char *value, size_t *size);
850 int erts_sys_explicit_8bit_putenv(char *key, char *value);
851 
852 /* This is identical to erts_sys_explicit_8bit_getenv but falls down to the
853  * host OS implementation instead of erts_osenv. */
854 int erts_sys_explicit_host_getenv(char *key, char *value, size_t *size);
855 
856 const erts_osenv_t *erts_sys_rlock_global_osenv(void);
857 void erts_sys_runlock_global_osenv(void);
858 
859 erts_osenv_t *erts_sys_rwlock_global_osenv(void);
860 void erts_sys_rwunlock_global_osenv(void);
861 
862 /* Easier to use, but not as efficient, environment functions */
863 char *erts_read_env(char *key);
864 void erts_free_read_env(void *value);
865 
866 #if defined(ERTS_THR_HAVE_SIG_FUNCS) &&                         \
867     (!defined(ETHR_UNUSABLE_SIGUSRX) || defined(SIGRTMIN))
868 extern void sys_thr_resume(erts_tid_t tid);
869 extern void sys_thr_suspend(erts_tid_t tid);
870 #ifdef SIGRTMIN
871 #define ERTS_SYS_SUSPEND_SIGNAL (SIGRTMIN+1)
872 #else
873 #define ERTS_SYS_SUSPEND_SIGNAL (SIGUSR2)
874 #endif /* SIGRTMIN */
875 #endif /* HAVE_SIG_FUNCS */
876 
877 /* utils.c */
878 
879 /* Options to sys_alloc_opt */
880 #define SYS_ALLOC_OPT_TRIM_THRESHOLD 0
881 #define SYS_ALLOC_OPT_TOP_PAD        1
882 #define SYS_ALLOC_OPT_MMAP_THRESHOLD 2
883 #define SYS_ALLOC_OPT_MMAP_MAX       3
884 
885 /* Default values to sys_alloc_opt options */
886 #define ERTS_DEFAULT_TRIM_THRESHOLD  (128 * 1024)
887 #define ERTS_DEFAULT_TOP_PAD         0
888 #define ERTS_DEFAULT_MMAP_THRESHOLD  (128 * 1024)
889 #define ERTS_DEFAULT_MMAP_MAX        64
890 
891 int sys_alloc_opt(int, int);
892 
893 typedef struct {
894   int trim_threshold;
895   int top_pad;
896   int mmap_threshold;
897   int mmap_max;
898 } SysAllocStat;
899 
900 void sys_alloc_stat(SysAllocStat *);
901 
902 #if defined(DEBUG) || defined(ERTS_ENABLE_LOCK_CHECK)
903 #undef ERTS_REFC_DEBUG
904 #define ERTS_REFC_DEBUG
905 #endif
906 
907 typedef erts_atomic_t erts_refc_t;
908 
909 ERTS_GLB_INLINE void erts_refc_init(erts_refc_t *refcp, erts_aint_t val);
910 ERTS_GLB_INLINE void erts_refc_inc(erts_refc_t *refcp, erts_aint_t min_val);
911 ERTS_GLB_INLINE erts_aint_t erts_refc_inc_unless(erts_refc_t *refcp,
912                                                  erts_aint_t unless_val,
913                                                  erts_aint_t min_val);
914 ERTS_GLB_INLINE void erts_refc_inc_if(erts_refc_t *refcp,
915                                       erts_aint_t if_val,
916                                       erts_aint_t min_val);
917 ERTS_GLB_INLINE erts_aint_t erts_refc_inctest(erts_refc_t *refcp,
918 					      erts_aint_t min_val);
919 ERTS_GLB_INLINE void erts_refc_dec(erts_refc_t *refcp, erts_aint_t min_val);
920 ERTS_GLB_INLINE erts_aint_t erts_refc_dectest(erts_refc_t *refcp,
921 					      erts_aint_t min_val);
922 ERTS_GLB_INLINE void erts_refc_add(erts_refc_t *refcp, erts_aint_t diff,
923 				   erts_aint_t min_val);
924 ERTS_GLB_INLINE erts_aint_t erts_refc_read(erts_refc_t *refcp,
925 					   erts_aint_t min_val);
926 
927 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
928 
929 ERTS_GLB_INLINE void
erts_refc_init(erts_refc_t * refcp,erts_aint_t val)930 erts_refc_init(erts_refc_t *refcp, erts_aint_t val)
931 {
932     erts_atomic_init_nob((erts_atomic_t *) refcp, val);
933 }
934 
935 ERTS_GLB_INLINE void
erts_refc_inc(erts_refc_t * refcp,erts_aint_t min_val)936 erts_refc_inc(erts_refc_t *refcp, erts_aint_t min_val)
937 {
938 #ifdef ERTS_REFC_DEBUG
939     erts_aint_t val = erts_atomic_inc_read_nob((erts_atomic_t *) refcp);
940     if (val < min_val)
941 	erts_exit(ERTS_ABORT_EXIT,
942 		 "erts_refc_inc(): Bad refc found (refc=%ld < %ld)!\n",
943 		 val, min_val);
944 #else
945     erts_atomic_inc_nob((erts_atomic_t *) refcp);
946 #endif
947 }
948 
949 ERTS_GLB_INLINE erts_aint_t
erts_refc_inc_unless(erts_refc_t * refcp,erts_aint_t unless_val,erts_aint_t min_val)950 erts_refc_inc_unless(erts_refc_t *refcp,
951                      erts_aint_t unless_val,
952                      erts_aint_t min_val)
953 {
954     erts_aint_t val = erts_atomic_read_nob((erts_atomic_t *) refcp);
955     while (1) {
956         erts_aint_t exp, new_value;
957 #ifdef ERTS_REFC_DEBUG
958         if (val < min_val)
959             erts_exit(ERTS_ABORT_EXIT,
960                       "erts_refc_inc_unless(): Bad refc found (refc=%ld < %ld)!\n",
961                       val, min_val);
962 #endif
963         if (val == unless_val)
964             return val;
965         new_value = val + 1;
966         exp = val;
967         val = erts_atomic_cmpxchg_nob((erts_atomic_t *) refcp, new_value, exp);
968         if (val == exp)
969             return new_value;
970     }
971 }
972 
973 ERTS_GLB_INLINE void
erts_refc_inc_if(erts_refc_t * refcp,erts_aint_t if_val,erts_aint_t min_val)974 erts_refc_inc_if(erts_refc_t *refcp,
975                  erts_aint_t if_val,
976                  erts_aint_t min_val)
977 {
978     erts_aint_t val = erts_atomic_read_nob((erts_atomic_t *) refcp);
979 #ifdef ERTS_REFC_DEBUG
980     if (val < min_val)
981         erts_exit(ERTS_ABORT_EXIT,
982                   "erts_refc_inc_unless(): Bad refc found (refc=%ld < %ld)!\n",
983                   val, min_val);
984 #endif
985     if (val == if_val) {
986         erts_atomic_cmpxchg_nob((erts_atomic_t *) refcp, val+1, val);
987         /*
988          * Ignore failure, as it means someone else took care of 'if_val'.
989          * Could be this function racing with itself.
990          */
991     }
992 }
993 
994 ERTS_GLB_INLINE erts_aint_t
erts_refc_inctest(erts_refc_t * refcp,erts_aint_t min_val)995 erts_refc_inctest(erts_refc_t *refcp, erts_aint_t min_val)
996 {
997     erts_aint_t val = erts_atomic_inc_read_nob((erts_atomic_t *) refcp);
998 #ifdef ERTS_REFC_DEBUG
999     if (val < min_val)
1000 	erts_exit(ERTS_ABORT_EXIT,
1001 		 "erts_refc_inctest(): Bad refc found (refc=%ld < %ld)!\n",
1002 		 val, min_val);
1003 #endif
1004     return val;
1005 }
1006 
1007 ERTS_GLB_INLINE void
erts_refc_dec(erts_refc_t * refcp,erts_aint_t min_val)1008 erts_refc_dec(erts_refc_t *refcp, erts_aint_t min_val)
1009 {
1010 #ifdef ERTS_REFC_DEBUG
1011     erts_aint_t val = erts_atomic_dec_read_nob((erts_atomic_t *) refcp);
1012     if (val < min_val)
1013 	erts_exit(ERTS_ABORT_EXIT,
1014 		 "erts_refc_dec(): Bad refc found (refc=%ld < %ld)!\n",
1015 		 val, min_val);
1016 #else
1017     erts_atomic_dec_nob((erts_atomic_t *) refcp);
1018 #endif
1019 }
1020 
1021 ERTS_GLB_INLINE erts_aint_t
erts_refc_dectest(erts_refc_t * refcp,erts_aint_t min_val)1022 erts_refc_dectest(erts_refc_t *refcp, erts_aint_t min_val)
1023 {
1024     erts_aint_t val = erts_atomic_dec_read_nob((erts_atomic_t *) refcp);
1025 #ifdef ERTS_REFC_DEBUG
1026     if (val < min_val)
1027 	erts_exit(ERTS_ABORT_EXIT,
1028 		 "erts_refc_dectest(): Bad refc found (refc=%ld < %ld)!\n",
1029 		 val, min_val);
1030 #endif
1031     return val;
1032 }
1033 
1034 ERTS_GLB_INLINE void
erts_refc_add(erts_refc_t * refcp,erts_aint_t diff,erts_aint_t min_val)1035 erts_refc_add(erts_refc_t *refcp, erts_aint_t diff, erts_aint_t min_val)
1036 {
1037 #ifdef ERTS_REFC_DEBUG
1038     erts_aint_t val = erts_atomic_add_read_nob((erts_atomic_t *) refcp, diff);
1039     if (val < min_val)
1040 	erts_exit(ERTS_ABORT_EXIT,
1041 		 "erts_refc_add(%ld): Bad refc found (refc=%ld < %ld)!\n",
1042 		 diff, val, min_val);
1043 #else
1044     erts_atomic_add_nob((erts_atomic_t *) refcp, diff);
1045 #endif
1046 }
1047 
1048 ERTS_GLB_INLINE erts_aint_t
erts_refc_read(erts_refc_t * refcp,erts_aint_t min_val)1049 erts_refc_read(erts_refc_t *refcp, erts_aint_t min_val)
1050 {
1051     erts_aint_t val = erts_atomic_read_nob((erts_atomic_t *) refcp);
1052 #ifdef ERTS_REFC_DEBUG
1053     if (val < min_val)
1054 	erts_exit(ERTS_ABORT_EXIT,
1055 		 "erts_refc_read(): Bad refc found (refc=%ld < %ld)!\n",
1056 		 val, min_val);
1057 #endif
1058     return val;
1059 }
1060 
1061 #endif  /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
1062 
1063 
1064 /* Thin wrappers around memcpy and friends, which should always be used in
1065  * place of plain memcpy, memset, etc.
1066  *
1067  * Passing NULL to any of these functions is undefined behavior even though it
1068  * may seemingly work when the length (if any) is zero; a compiler can take
1069  * this as a hint that the passed operand may *never* be NULL and then optimize
1070  * based on that information.
1071  */
1072 ERTS_GLB_INLINE void *sys_memcpy(void *dest, const void *src, size_t n);
1073 ERTS_GLB_INLINE void *sys_memmove(void *dest, const void *src, size_t n);
1074 ERTS_GLB_INLINE int sys_memcmp(const void *s1, const void *s2, size_t n);
1075 ERTS_GLB_INLINE void *sys_memset(void *s, int c, size_t n);
1076 ERTS_GLB_INLINE void *sys_memzero(void *s, size_t n);
1077 ERTS_GLB_INLINE int sys_strcmp(const char *s1, const char *s2);
1078 ERTS_GLB_INLINE int sys_strncmp(const char *s1, const char *s2, size_t n);
1079 ERTS_GLB_INLINE char *sys_strcpy(char *dest, const char *src);
1080 ERTS_GLB_INLINE char *sys_strncpy(char *dest, const char *src, size_t n);
1081 ERTS_GLB_INLINE size_t sys_strlen(const char *s);
1082 
1083 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1084 
sys_memcpy(void * dest,const void * src,size_t n)1085 ERTS_GLB_INLINE void *sys_memcpy(void *dest, const void *src, size_t n)
1086 {
1087     ASSERT(dest != NULL && src != NULL);
1088     return memcpy(dest,src,n);
1089 }
sys_memmove(void * dest,const void * src,size_t n)1090 ERTS_GLB_INLINE void *sys_memmove(void *dest, const void *src, size_t n)
1091 {
1092     ASSERT(dest != NULL && src != NULL);
1093     return memmove(dest,src,n);
1094 }
sys_memcmp(const void * s1,const void * s2,size_t n)1095 ERTS_GLB_INLINE int sys_memcmp(const void *s1, const void *s2, size_t n)
1096 {
1097     ASSERT(s1 != NULL && s2 != NULL);
1098     return memcmp(s1,s2,n);
1099 }
sys_memset(void * s,int c,size_t n)1100 ERTS_GLB_INLINE void *sys_memset(void *s, int c, size_t n)
1101 {
1102     ASSERT(s != NULL);
1103     return memset(s,c,n);
1104 }
sys_memzero(void * s,size_t n)1105 ERTS_GLB_INLINE void *sys_memzero(void *s, size_t n)
1106 {
1107     ASSERT(s != NULL);
1108     return memset(s,'\0',n);
1109 }
sys_strcmp(const char * s1,const char * s2)1110 ERTS_GLB_INLINE int sys_strcmp(const char *s1, const char *s2)
1111 {
1112     ASSERT(s1 != NULL && s2 != NULL);
1113     return strcmp(s1,s2);
1114 }
sys_strncmp(const char * s1,const char * s2,size_t n)1115 ERTS_GLB_INLINE int sys_strncmp(const char *s1, const char *s2, size_t n)
1116 {
1117     ASSERT(s1 != NULL && s2 != NULL);
1118     return strncmp(s1,s2,n);
1119 }
sys_strcpy(char * dest,const char * src)1120 ERTS_GLB_INLINE char *sys_strcpy(char *dest, const char *src)
1121 {
1122     ASSERT(dest != NULL && src != NULL);
1123     return strcpy(dest,src);
1124 
1125 }
sys_strncpy(char * dest,const char * src,size_t n)1126 ERTS_GLB_INLINE char *sys_strncpy(char *dest, const char *src, size_t n)
1127 {
1128     ASSERT(dest != NULL && src != NULL);
1129     return strncpy(dest,src,n);
1130 }
sys_strlen(const char * s)1131 ERTS_GLB_INLINE size_t sys_strlen(const char *s)
1132 {
1133     ASSERT(s != NULL);
1134     return strlen(s);
1135 }
1136 #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
1137 
1138 /* define function symbols (needed in sys_drv_api) */
1139 #define sys_fp_alloc     sys_alloc
1140 #define sys_fp_realloc   sys_realloc
1141 #define sys_fp_free      sys_free
1142 #define sys_fp_memcpy    memcpy
1143 #define sys_fp_memmove   memmove
1144 #define sys_fp_memcmp    memcmp
1145 #define sys_fp_memset    memset
1146 /* #define sys_fp_memzero    elib_memzero */
1147 #define sys_fp_strcmp    strcmp
1148 #define sys_fp_strncmp   strncmp
1149 #define sys_fp_strcpy    strcpy
1150 #define sys_fp_strncpy   strncpy
1151 #define sys_fp_strlen    strlen
1152 
1153 
1154 /* Return codes from the nb_read and nb_write functions */
1155 #define FD_READY 1
1156 #define FD_CONTINUE 2
1157 #define FD_ERROR 3
1158 
1159 
1160 
1161 /* Standard set of integer macros  .. */
1162 
1163 #define get_int64(s) (((Uint64)(((byte*) (s))[0]) << 56) | \
1164                       (((Uint64)((byte*) (s))[1]) << 48) | \
1165                       (((Uint64)((byte*) (s))[2]) << 40) | \
1166                       (((Uint64)((byte*) (s))[3]) << 32) | \
1167                       (((Uint64)((byte*) (s))[4]) << 24) | \
1168                       (((Uint64)((byte*) (s))[5]) << 16) | \
1169                       (((Uint64)((byte*) (s))[6]) << 8)  | \
1170                       (((Uint64)((byte*) (s))[7])))
1171 
1172 #define put_int64(i, s) do {((byte*)(s))[0] = (byte)((Sint64)(i) >> 56) & 0xff;\
1173                             ((byte*)(s))[1] = (byte)((Sint64)(i) >> 48) & 0xff;\
1174                             ((byte*)(s))[2] = (byte)((Sint64)(i) >> 40) & 0xff;\
1175                             ((byte*)(s))[3] = (byte)((Sint64)(i) >> 32) & 0xff;\
1176                             ((byte*)(s))[4] = (byte)((Sint64)(i) >> 24) & 0xff;\
1177                             ((byte*)(s))[5] = (byte)((Sint64)(i) >> 16) & 0xff;\
1178                             ((byte*)(s))[6] = (byte)((Sint64)(i) >> 8)  & 0xff;\
1179                             ((byte*)(s))[7] = (byte)((Sint64)(i))       & 0xff;\
1180                            } while (0)
1181 
1182 /* Returns a signed int */
1183 #define get_int32(s) ((((byte*) (s))[0] << 24) | \
1184                       (((byte*) (s))[1] << 16) | \
1185                       (((byte*) (s))[2] << 8)  | \
1186                       (((byte*) (s))[3]))
1187 
1188 #define get_little_int32(s) ((((byte*) (s))[3] << 24) | \
1189 			     (((byte*) (s))[2] << 16)  | \
1190 			     (((byte*) (s))[1] << 8) | \
1191 			     (((byte*) (s))[0]))
1192 
1193 #define get_uint32(s) ((Uint32)get_int32(s))
1194 
1195 #define put_int32(i, s) do {((byte*)(s))[0] = (byte)((i) >> 24) & 0xff;  \
1196                             ((byte*)(s))[1] = (byte)((i) >> 16) & 0xff;  \
1197                             ((byte*)(s))[2] = (byte)((i) >> 8)  & 0xff;  \
1198                             ((byte*)(s))[3] = (byte)(i)         & 0xff;} \
1199                         while (0)
1200 
1201 #define get_int24(s) ((((byte*) (s))[0] << 16) | \
1202                       (((byte*) (s))[1] << 8)  | \
1203                       (((byte*) (s))[2]))
1204 
1205 
1206 #define put_int24(i, s) do {((byte*)(s))[0] = (byte)((i) >> 16) & 0xff;  \
1207                             ((byte*)(s))[1] = (byte)((i) >> 8)  & 0xff;  \
1208                             ((byte*)(s))[2] = (byte)(i)         & 0xff;} \
1209                         while (0)
1210 
1211 #define get_int16(s) ((((byte*)  (s))[0] << 8) | \
1212                       (((byte*)  (s))[1]))
1213 
1214 
1215 #define put_int16(i, s) do {((byte*)(s))[0] = (byte)((i) >> 8) & 0xff;  \
1216                             ((byte*)(s))[1] = (byte)(i)        & 0xff;} \
1217                         while (0)
1218 
1219 #define get_int8(s) ((((byte*)  (s))[0] ))
1220 
1221 
1222 #define put_int8(i, s) do {((byte*)(s))[0] = (i) & 0xff;} while (0)
1223 
1224 /*
1225  * Use DEBUGF as you would use printf, but use double parentheses:
1226  *
1227  *   DEBUGF(("Error: %s\n", error));
1228  *
1229  * The output will appear in a special console.
1230  */
1231 
1232 #ifdef DEBUG
1233 void erl_debug(char* format, ...);
1234 void erl_bin_write(unsigned char *, int, int);
1235 
1236 #  define DEBUGF(x) erl_debug x
1237 #else
1238 #  define DEBUGF(x)
1239 #endif
1240 
1241 #ifndef MAX
1242 #define MAX(A, B) ((A) > (B) ? (A) : (B))
1243 #endif
1244 
1245 #ifndef MIN
1246 #define MIN(A, B) ((A) < (B) ? (A) : (B))
1247 #endif
1248 
1249 #ifdef __WIN32__
1250 #ifdef ARCH_64
1251 #define ERTS_ALLOC_ALIGN_BYTES 16
1252 #define ERTS_SMALL_ABS(Small) _abs64(Small)
1253 #else
1254 #define ERTS_ALLOC_ALIGN_BYTES 8
1255 #define ERTS_SMALL_ABS(Small) labs(Small)
1256 #endif
1257 #else
1258 #define ERTS_ALLOC_ALIGN_BYTES 8
1259 #define ERTS_SMALL_ABS(Small) labs(Small)
1260 #endif
1261 
1262 #ifndef ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC
1263 #  define ERTS_HAVE_ERTS_SYS_ALIGNED_ALLOC 0
1264 #endif
1265 
1266 #ifdef __WIN32__
1267 void call_break_handler(void);
1268 char* last_error(void);
1269 char* win32_errorstr(int);
1270 #endif
1271 
1272 /************************************************************************
1273  * Find out the native filename encoding of the process (look at locale of
1274  * Unix processes and just do UTF16 on windows
1275  ************************************************************************/
1276 #define ERL_FILENAME_UNKNOWN   (0)
1277 #define ERL_FILENAME_LATIN1    (1)
1278 #define ERL_FILENAME_UTF8      (2)
1279 #define ERL_FILENAME_UTF8_MAC  (3)
1280 #define ERL_FILENAME_WIN_WCHAR (4)
1281 
1282 /************************************************************************
1283  * If a filename in for example list_dir is not in the right encoding, it
1284  * will be skipped in the resulting list, but depending on a startup setting
1285  * we will inform the user in different ways. These macros define the
1286  * different reactions to wrongly coded filenames. In the error case an
1287  * exception will be thrown by prim_file.
1288  ************************************************************************/
1289 #define ERL_FILENAME_WARNING_WARNING (0)
1290 #define ERL_FILENAME_WARNING_IGNORE (1)
1291 #define ERL_FILENAME_WARNING_ERROR (2)
1292 
1293 /***********************************************************************
1294  * The user can request a range of character that he/she consider
1295  * printable. Currently this can be either latin1 or unicode, but
1296  * in the future a set of ranges, or languages, could be specified.
1297  ***********************************************************************/
1298 #define ERL_PRINTABLE_CHARACTERS_LATIN1 (0)
1299 #define ERL_PRINTABLE_CHARACTERS_UNICODE (1)
1300 
1301 int erts_get_native_filename_encoding(void);
1302 /* The set function is only to be used by erl_init! */
1303 void erts_set_user_requested_filename_encoding(int encoding, int warning);
1304 int erts_get_user_requested_filename_encoding(void);
1305 int erts_get_filename_warning_type(void);
1306 /* This function is called from erl_init. The setting is read by BIF's
1307    in io/io_lib. Setting is not atomic. */
1308 void erts_set_printable_characters(int range);
1309 /* Get the setting (ERL_PRINTABLE_CHARACTERS_{LATIN1|UNICODE} */
1310 int erts_get_printable_characters(void);
1311 
1312 void erts_init_sys_common_misc(void);
1313 
1314 ERTS_GLB_INLINE Sint erts_raw_env_7bit_ascii_char_need(int encoding);
1315 ERTS_GLB_INLINE byte *erts_raw_env_7bit_ascii_char_put(byte c, byte *p,
1316                                                        int encoding);
1317 ERTS_GLB_INLINE int  erts_raw_env_char_is_7bit_ascii_char(byte c, byte *p,
1318                                                           int encoding);
1319 ERTS_GLB_INLINE byte *erts_raw_env_next_char(byte *p, int encoding);
1320 
1321 #if ERTS_GLB_INLINE_INCL_FUNC_DEF
1322 
1323 ERTS_GLB_INLINE Sint
erts_raw_env_7bit_ascii_char_need(int encoding)1324 erts_raw_env_7bit_ascii_char_need(int encoding)
1325 {
1326     return (encoding == ERL_FILENAME_WIN_WCHAR) ? 2 : 1;
1327 }
1328 
1329 ERTS_GLB_INLINE byte *
erts_raw_env_7bit_ascii_char_put(byte c,byte * p,int encoding)1330 erts_raw_env_7bit_ascii_char_put(byte c,
1331                                  byte *p,
1332                                  int encoding)
1333 {
1334     *(p++) = c;
1335     if (encoding == ERL_FILENAME_WIN_WCHAR)
1336         *(p++) = 0;
1337     return p;
1338 }
1339 
1340 ERTS_GLB_INLINE int
erts_raw_env_char_is_7bit_ascii_char(byte c,byte * p,int encoding)1341 erts_raw_env_char_is_7bit_ascii_char(byte c,
1342                                      byte *p,
1343                                      int encoding)
1344 {
1345     if (encoding == ERL_FILENAME_WIN_WCHAR)
1346         return (p[0] == c) & (p[1] == 0);
1347     else
1348         return p[0] == c;
1349 }
1350 
1351 ERTS_GLB_INLINE byte *
erts_raw_env_next_char(byte * p,int encoding)1352 erts_raw_env_next_char(byte *p, int encoding)
1353 {
1354     if (encoding == ERL_FILENAME_WIN_WCHAR)
1355         return p + 2;
1356     else
1357         return p + 1;
1358 }
1359 
1360 #endif /* #if ERTS_GLB_INLINE_INCL_FUNC_DEF */
1361 
1362 /*
1363  * Magic numbers for our driver port_control callbacks.
1364  * Kept them below 1<<27 to not inflict extra bignum garbage on 32-bit.
1365  */
1366 #define ERTS_TTYSL_DRV_CONTROL_MAGIC_NUMBER  0x018b0900U
1367 #define ERTS_INET_DRV_CONTROL_MAGIC_NUMBER   0x03f1a300U
1368 #define ERTS_SPAWN_DRV_CONTROL_MAGIC_NUMBER  0x04c76a00U
1369 #define ERTS_FORKER_DRV_CONTROL_MAGIC_NUMBER 0x050a7800U
1370 
1371 #endif
1372