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