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