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