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