summaryrefslogtreecommitdiff
path: root/src/pal/src/include/pal/palinternal.h
blob: 7348192e6d88e4d989e260c23dce77b12ffde292 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

/*++



Module Name:

    palinternal.h

Abstract:

    Rotor Platform Adaptation Layer (PAL) header file used by source
    file part of the PAL implementation. This is a wrapper over 
    unix/inc/pal.h. It allows avoiding name collisions when including 
    system header files, and it allows redirecting calls to 'standard' functions
    to their PAL counterpart

Details :

A] Rationale (see B] for the quick recipe)
There are 2 types of namespace collisions that must be handled.

1) standard functions declared in pal.h, which do not need to be 
   implemented in the PAL because the system's implementation is sufficient.

   (examples : memcpy, strlen, fclose)

   The problem with these is that a prototype for them is provided both in 
   pal.h and in a system header (stdio.h, etc). If a PAL file needs to 
   include the files containing both prototypes, the compiler may complain 
   about the multiple declarations.

   To avoid this, the inclusion of pal.h must be wrapped in a 
   #define/#undef pair, which will effectiveily "hide" the pal.h 
   declaration by renaming it to something else. this is done by palinternal.h
   in this way :

   #define some_function DUMMY_some_function
   #include <pal.h>
   #undef some_function

   when a PAL source file includes palinternal.h, it will see a prototype for 
   DUMMY_some_function instead of some_function; so when it includes the 
   system header with the "real" prototype, no collision occurs.

   (note : technically, no functions should ever be treated this way, all 
   system functions should be wrapped according to method 2, so that call 
   logging through ENTRY macros is done for all functions n the PAL. However 
   this reason alone is not currently considered enough to warrant a wrapper)

2) standard functions which must be reimplemented by the PAL, because the 
   system's implementation does not offer suitable functionnality.
   
   (examples : widestring functions, networking)
   
   Here, the problem is more complex. The PAL must provide functions with the 
   same name as system functions. Due to the nature of Unix dynamic linking, 
   if this is done, the PAL's implementation will effectively mask the "real" 
   function, so that all calls are directed to it. This makes it impossible for
   a function to be implemented as calling its counterpart in the system, plus 
   some extra work, because instead of calling the system's implementation, the
   function would only call itself in an infinitely recursing nightmare. Even 
   worse, if by bad luck the system libraries attempt to call the function for 
   which the PAL provides an implementation, it is the PAL's version that will 
   be called.
   It is therefore necessary to give the PAL's implementation of such functions
   a different name. However, PAL consumers (applications built on top of the 
   PAL) must be able to call the function by its 'official' name, not the PAL's 
   internal name. 
   This can be done with some more macro magic, by #defining the official name 
   to the internal name *in pal.h*. :

   #define some_function PAL_some_function

   This way, while PAL consumer code can use the official name, it is the 
   internal name that wil be seen at compile time.
   However, one extra step is needed. While PAL consumers must use the PAL's 
   implementation of these functions, the PAL itself must still have access to
   the "real" functions. This is done by #undefining in palinternal.h the names
   #defined in pal.h :

   #include <pal.h>
   #undef some_function.

   At this point, code in the PAL implementation can access *both* its own 
   implementation of the function (with PAL_some_function) *and* the system's 
   implementation (with some_function)

    [side note : for the Win32 PAL, this can be accomplished without touching 
    pal.h. In Windows, symbols in in dynamic libraries are resolved at 
    compile time. if an application that uses some_function is only linked to 
    pal.dll, some_function will be resolved to the version in that DLL, 
    even if other DLLs in the system provide other implementations. In addition,
    the function in the DLL can actually have a different name (e.g. 
    PAL_some_function), to which the 'official' name is aliased when the DLL 
    is compiled. All this is not possible with Unix dynamic linking, where 
    symbols are resolved at run-time in a first-found-first-used order. A 
    module may end up using the symbols from a module it was never linked with,
    simply because that module was located somewhere in the dependency chain. ]

    It should be mentionned that even if a function name is not documented as 
    being implemented in the system, it can still cause problems if it exists. 
    This is especially a problem for functions in the "reserved" namespace 
    (names starting with an underscore : _exit, etc). (We shouldn't really be 
    implementing functions with such a name, but we don't really have a choice)
    If such a case is detected, it should be wrapped according to method 2

    Note that for all this to work, it is important for the PAL's implementation
    files to #include palinternal.h *before* any system files, and to never 
    include pal.h directly.

B] Procedure for name conflict resolution :

When adding a function to pal.h, which is implemented by the system and 
which does not need a different implementation :

- add a #define function_name DUMMY_function_name to palinternal.h, after all 
  the other DUMMY_ #defines (above the #include <pal.h> line)
- add the function's prototype to pal.h (if that isn't already done)
- add a #undef function_name to palinternal.h near all the other #undefs 
  (after the #include <pal.h> line)
  
When overriding a system function with the PAL's own implementation :

- add a #define function_name PAL_function_name to pal.h, somewhere 
  before the function's prototype, inside a #ifndef _MSCVER/#endif pair 
  (to avoid affecting the Win32 build)
- add a #undef function_name to palinternal.h near all the other #undefs 
  (after the #include <pal.h> line)
- implement the function in the pal, naming it PAL_function_name
- within the PAL, call PAL_function_name() to call the PAL's implementation, 
function_name() to call the system's implementation



--*/

#ifndef _PAL_INTERNAL_H_
#define _PAL_INTERNAL_H_

#define PAL_IMPLEMENTATION

/* Include our configuration information so it's always present when
   compiling PAL implementation files. */
#include "config.h"

#ifdef DEBUG
#define _ENABLE_DEBUG_MESSAGES_ 1
#else
#define _ENABLE_DEBUG_MESSAGES_ 0
#endif

#ifdef PAL_PERF
#include "pal_perf.h"
#endif

/* C runtime functions needed to be renamed to avoid duplicate definition
   of those functions when including standard C header files */
#define div DUMMY_div
#define div_t DUMMY_div_t
#if !defined(_DEBUG)
#define memcpy DUMMY_memcpy 
#endif //!defined(_DEBUG)
#define memcmp DUMMY_memcmp 
#define memset DUMMY_memset 
#define memmove DUMMY_memmove 
#define memchr DUMMY_memchr
#define strlen DUMMY_strlen
#define strnlen DUMMY_strnlen
#define stricmp DUMMY_stricmp 
#define strstr DUMMY_strstr 
#define strcmp DUMMY_strcmp 
#define strcat DUMMY_strcat
#define strncat DUMMY_strncat
#define strcpy DUMMY_strcpy
#define strcspn DUMMY_strcspn
#define strncmp DUMMY_strncmp
#define strncpy DUMMY_strncpy
#define strchr DUMMY_strchr
#define strrchr DUMMY_strrchr 
#define strpbrk DUMMY_strpbrk
#define strtod DUMMY_strtod
#define strspn DUMMY_strspn
#if HAVE__SNPRINTF
#define _snprintf DUMMY__snprintf
#endif /* HAVE__SNPRINTF */
#if HAVE__SNWPRINTF
#define _snwprintf DUMMY__snwprintf
#endif  /* HAVE__SNWPRINTF */
#define tolower DUMMY_tolower
#define toupper DUMMY_toupper
#define islower DUMMY_islower
#define isupper DUMMY_isupper
#define isprint DUMMY_isprint
#define isdigit DUMMY_isdigit
#define srand DUMMY_srand
#define atoi DUMMY_atoi
#define atof DUMMY_atof
#define tm PAL_tm
#define size_t DUMMY_size_t
#define time_t PAL_time_t
#define va_list DUMMY_va_list
#define abs DUMMY_abs
#define llabs DUMMY_llabs
#define ceil DUMMY_ceil
#define cos DUMMY_cos
#define cosh DUMMY_cosh
#define fabs DUMMY_fabs
#define floor DUMMY_floor
#define fmod DUMMY_fmod
#define modf DUMMY_modf
#define sin DUMMY_sin
#define sinh DUMMY_sinh
#define sqrt DUMMY_sqrt
#define tan DUMMY_tan
#define tanh DUMMY_tanh
#define fabsf DUMMY_fabsf
#define fmodf DUMMY_fmodf
#define modff DUMMY_modff

/* RAND_MAX needed to be renamed to avoid duplicate definition when including 
   stdlib.h header files. PAL_RAND_MAX should have the same value as RAND_MAX 
   defined in pal.h  */
#define PAL_RAND_MAX 0x7fff

/* The standard headers define isspace and isxdigit as macros and functions,
   To avoid redefinition problems, undefine those macros. */
#ifdef isspace
#undef isspace
#endif
#ifdef isxdigit
#undef isxdigit
#endif
#ifdef isalpha
#undef isalpha
#endif
#ifdef isalnum
#undef isalnum
#endif
#define isspace DUMMY_isspace 
#define isxdigit DUMMY_isxdigit
#define isalpha DUMMY_isalpha
#define isalnum DUMMY_isalnum

#ifdef stdin
#undef stdin
#endif
#ifdef stdout
#undef stdout
#endif
#ifdef stderr
#undef stderr
#endif

#ifdef SCHAR_MIN
#undef SCHAR_MIN
#endif
#ifdef SCHAR_MAX
#undef SCHAR_MAX
#endif
#ifdef SHRT_MIN
#undef SHRT_MIN
#endif
#ifdef SHRT_MAX
#undef SHRT_MAX
#endif
#ifdef UCHAR_MAX
#undef UCHAR_MAX
#endif
#ifdef USHRT_MAX
#undef USHRT_MAX
#endif
#ifdef ULONG_MAX
#undef ULONG_MAX
#endif
#ifdef LONG_MIN
#undef LONG_MIN
#endif
#ifdef LONG_MAX
#undef LONG_MAX
#endif
#ifdef RAND_MAX
#undef RAND_MAX
#endif
#ifdef DBL_MAX
#undef DBL_MAX
#endif
#ifdef FLT_MAX
#undef FLT_MAX
#endif
#ifdef __record_type_class
#undef __record_type_class
#endif
#ifdef __real_type_class
#undef __real_type_class
#endif

// The standard headers define va_start and va_end as macros,
// To avoid redefinition problems, undefine those macros.
#ifdef va_start
#undef va_start
#endif
#ifdef va_end
#undef va_end
#endif
#ifdef va_copy
#undef va_copy
#endif


#ifdef _VAC_
#define wchar_16 wchar_t
#else
#define wchar_t wchar_16
#endif // _VAC_

#define ptrdiff_t PAL_ptrdiff_t
#define intptr_t PAL_intptr_t
#define uintptr_t PAL_uintptr_t
#define timeval PAL_timeval
#define FILE PAL_FILE

#include "pal.h"
#include "palprivate.h"

#include "mbusafecrt.h"

#ifdef _VAC_
#undef CHAR_BIT
#undef va_arg
#endif

#if !defined(_MSC_VER) && defined(FEATURE_PAL) && defined(_WIN64)
#undef _BitScanForward64
#endif 

/* pal.h defines alloca(3) as a compiler builtin.
   Redefining it to native libc will result in undefined breakage because
   a compiler is allowed to make assumptions about the stack and frame
   pointers. */

/* Undef all functions and types previously defined so those functions and
   types could be mapped to the C runtime and socket implementation of the 
   native OS */
#undef exit
#undef atexit
#undef div
#undef div_t
#if !defined(_DEBUG)
#undef memcpy
#endif //!defined(_DEBUG)
#undef memcmp
#undef memset
#undef memmove
#undef memchr
#undef strlen
#undef strnlen
#undef stricmp
#undef strstr
#undef strcmp
#undef strcat
#undef strcspn
#undef strncat
#undef strcpy
#undef strncmp
#undef strncpy
#undef strchr
#undef strrchr
#undef strpbrk
#undef strtoul
#undef strtod
#undef strspn
#undef strtok
#undef strdup
#undef tolower
#undef toupper
#undef islower
#undef isupper
#undef isprint
#undef isdigit
#undef isspace
#undef iswdigit
#undef iswxdigit
#undef iswalpha
#undef iswprint
#undef isxdigit
#undef isalpha
#undef isalnum
#undef atoi
#undef atol
#undef atof
#undef malloc
#undef realloc
#undef free
#undef qsort
#undef bsearch
#undef time
#undef tm
#undef localtime
#undef mktime
#undef FILE
#undef fclose
#undef setbuf
#undef fopen
#undef fread
#undef feof
#undef ferror
#undef ftell
#undef fflush
#undef fwrite
#undef fgets
#undef fgetws
#undef fputc
#undef putchar
#undef fputs
#undef fseek
#undef fgetpos
#undef fsetpos
#undef getcwd
#undef getc
#undef fgetc
#undef ungetc
#undef _flushall
#undef setvbuf
#undef mkstemp
#undef rename
#undef unlink
#undef size_t
#undef time_t
#undef va_list
#undef va_start
#undef va_end
#undef va_copy
#undef stdin
#undef stdout
#undef stderr
#undef abs
#undef labs
#undef llabs
#undef acos
#undef asin
#undef atan
#undef atan2
#undef ceil
#undef cos
#undef cosh
#undef exp
#undef fabs
#undef floor
#undef fmod
#undef log
#undef log10
#undef modf
#undef pow
#undef sin
#undef sinh
#undef sqrt
#undef tan
#undef tanh
#undef fabsf
#undef fmodf
#undef modff
#undef rand
#undef srand
#undef errno
#undef getenv 
#undef wcsspn
#undef open
#undef glob

#undef wchar_t
#undef ptrdiff_t
#undef intptr_t
#undef uintptr_t
#undef timeval


#undef printf
#undef fprintf
#undef fwprintf
#undef vfprintf
#undef vfwprintf
#undef vprintf
#undef wprintf
#undef sprintf
#undef swprintf
#undef _snprintf
#if HAVE__SNWPRINTF
#undef _snwprintf
#endif  /* HAVE__SNWPRINTF */
#undef sscanf
#undef wcstod
#undef wcstol
#undef wcstoul
#undef _wcstoui64
#undef wcscat
#undef wcscpy
#undef wcslen
#undef wcsncmp
#undef wcschr
#undef wcsrchr
#undef wsprintf
#undef swscanf
#undef wcspbrk
#undef wcsstr
#undef wcscmp
#undef wcsncat
#undef wcsncpy
#undef wcstok
#undef wcscspn
#undef iswupper
#undef iswspace
#undef towlower
#undef towupper
#undef vsprintf
#undef vswprintf
#undef _vsnprintf
#undef _vsnwprintf
#undef vsnprintf
#undef wvsnprintf

#ifdef _AMD64_ 
#undef _mm_getcsr
#undef _mm_setcsr
#endif // _AMD64_

#undef ctime

#undef SCHAR_MIN
#undef SCHAR_MAX
#undef UCHAR_MAX
#undef SHRT_MIN
#undef SHRT_MAX
#undef USHRT_MAX
#undef LONG_MIN
#undef LONG_MAX
#undef ULONG_MAX
#undef RAND_MAX
#undef DBL_MAX
#undef FLT_MAX
#undef __record_type_class
#undef __real_type_class

#if HAVE_CHAR_BIT
#undef CHAR_BIT
#endif

// We need a sigsetjmp prototype in pal.h for the SEH macros, but we
// can't use the "real" prototype (because we don't want to define sigjmp_buf).
// So we must rename the "real" sigsetjmp to avoid redefinition errors.
#define sigsetjmp REAL_sigsetjmp
#define siglongjmp REAL_siglongjmp
#include <setjmp.h>
#undef sigsetjmp
#undef siglongjmp

#undef _SIZE_T_DEFINED
#undef _WCHAR_T_DEFINED

#define _DONT_USE_CTYPE_INLINE_
#if HAVE_RUNETYPE_H
#include <runetype.h>
#endif
#include <ctype.h>

// Don't use C++ wrappers for stdlib.h
// https://gcc.gnu.org/ml/libstdc++/2016-01/msg00025.html 
#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS 1

#define _WITH_GETLINE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <unistd.h>
#include <fcntl.h>
#include <glob.h>

#ifdef __APPLE__

#undef GetCurrentThread
#include <CoreServices/CoreServices.h>

#include <malloc/malloc.h>

#endif // __APPLE__

/* we don't really need this header here, but by including it we make sure
   we'll catch any definition conflicts */
#include <sys/socket.h>

#if !HAVE_INFTIM
#define INFTIM  -1
#endif // !HAVE_INFTIM

#if (__GNUC__ >= 4)
#define OffsetOf(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
#else
#define OffsetOf(s, f) (INT)(SIZE_T)&(((s*)0)->f)
#endif /* __GNUC__ version check*/

#undef assert
#define assert (Use__ASSERTE_instead_of_assert) assert

#define PROCESS_PIPE_NAME_PREFIX ".dotnet-pal-processpipe"

#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus

typedef enum _TimeConversionConstants
{
    tccSecondsToMillieSeconds       = 1000,         // 10^3
    tccSecondsToMicroSeconds        = 1000000,      // 10^6
    tccSecondsToNanoSeconds         = 1000000000,   // 10^9
    tccMillieSecondsToMicroSeconds  = 1000,         // 10^3
    tccMillieSecondsToNanoSeconds   = 1000000,      // 10^6
    tccMicroSecondsToNanoSeconds    = 1000,         // 10^3
    tccSecondsTo100NanoSeconds      = 10000000,     // 10^7
    tccMicroSecondsTo100NanoSeconds = 10            // 10^1
} TimeConversionConstants;

#ifdef __cplusplus
}

/* This is duplicated in utilcode.h for CLR, with cooler type-traits */
template <typename T>
inline
T* InterlockedExchangePointerT(
    T* volatile *Target,
    T* Value)
{
    return (T*)(InterlockedExchangePointer(
        (PVOID volatile*)Target,
        (PVOID)Value));
}

template <typename T>
inline
T* InterlockedCompareExchangePointerT(
    T* volatile *destination,
    T* exchange,
    T* comparand)
{
    return (T*)(InterlockedCompareExchangePointer(
        (PVOID volatile*)destination,
        (PVOID)exchange,
        (PVOID)comparand));
}

template <typename T>
inline T* InterlockedExchangePointerT(
    T* volatile * target,
    int           value) // When NULL is provided as argument.
{
    //STATIC_ASSERT(value == 0);
    return InterlockedExchangePointerT(target, reinterpret_cast<T*>(value));
}

template <typename T>
inline T* InterlockedCompareExchangePointerT(
    T* volatile * destination,
    int           exchange,  // When NULL is provided as argument.
    T*            comparand)
{
    //STATIC_ASSERT(exchange == 0);
    return InterlockedCompareExchangePointerT(destination, reinterpret_cast<T*>(exchange), comparand);
}

template <typename T>
inline T* InterlockedCompareExchangePointerT(
    T* volatile * destination,
    T*            exchange,
    int           comparand) // When NULL is provided as argument.
{
    //STATIC_ASSERT(comparand == 0);
    return InterlockedCompareExchangePointerT(destination, exchange, reinterpret_cast<T*>(comparand));
}

#undef InterlockedExchangePointer
#define InterlockedExchangePointer InterlockedExchangePointerT
#undef InterlockedCompareExchangePointer
#define InterlockedCompareExchangePointer InterlockedCompareExchangePointerT

#include "volatile.h"

const char StackOverflowMessage[] = "Process is terminated due to StackOverflowException.\n";

#endif // __cplusplus

#endif /* _PAL_INTERNAL_H_ */