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