summaryrefslogtreecommitdiff
path: root/src/pal/src/include/pal
diff options
context:
space:
mode:
Diffstat (limited to 'src/pal/src/include/pal')
-rw-r--r--src/pal/src/include/pal/cert.hpp33
-rw-r--r--src/pal/src/include/pal/context.h641
-rw-r--r--src/pal/src/include/pal/corunix.hpp1359
-rw-r--r--src/pal/src/include/pal/corunix.inl55
-rw-r--r--src/pal/src/include/pal/critsect.h45
-rw-r--r--src/pal/src/include/pal/cruntime.h247
-rw-r--r--src/pal/src/include/pal/cs.hpp54
-rw-r--r--src/pal/src/include/pal/dbgmsg.h628
-rw-r--r--src/pal/src/include/pal/debug.h86
-rw-r--r--src/pal/src/include/pal/dtraceprotocol.h39
-rw-r--r--src/pal/src/include/pal/environ.h78
-rw-r--r--src/pal/src/include/pal/event.hpp69
-rw-r--r--src/pal/src/include/pal/fakepoll.h68
-rw-r--r--src/pal/src/include/pal/file.h304
-rw-r--r--src/pal/src/include/pal/file.hpp365
-rw-r--r--src/pal/src/include/pal/filetime.h80
-rw-r--r--src/pal/src/include/pal/handleapi.hpp48
-rw-r--r--src/pal/src/include/pal/handlemgr.hpp180
-rw-r--r--src/pal/src/include/pal/identity.hpp57
-rw-r--r--src/pal/src/include/pal/init.h111
-rw-r--r--src/pal/src/include/pal/list.h141
-rw-r--r--src/pal/src/include/pal/locale.h75
-rw-r--r--src/pal/src/include/pal/malloc.hpp152
-rw-r--r--src/pal/src/include/pal/map.h52
-rw-r--r--src/pal/src/include/pal/map.hpp209
-rw-r--r--src/pal/src/include/pal/misc.h83
-rw-r--r--src/pal/src/include/pal/module.h203
-rw-r--r--src/pal/src/include/pal/modulename.h39
-rw-r--r--src/pal/src/include/pal/mutex.hpp191
-rw-r--r--src/pal/src/include/pal/palinternal.h696
-rw-r--r--src/pal/src/include/pal/perftrace.h70
-rw-r--r--src/pal/src/include/pal/printfcpp.hpp133
-rw-r--r--src/pal/src/include/pal/process.h162
-rw-r--r--src/pal/src/include/pal/procobj.hpp125
-rw-r--r--src/pal/src/include/pal/seh.hpp185
-rw-r--r--src/pal/src/include/pal/semaphore.hpp74
-rw-r--r--src/pal/src/include/pal/sharedmemory.h268
-rw-r--r--src/pal/src/include/pal/sharedmemory.inl53
-rw-r--r--src/pal/src/include/pal/shm.hpp83
-rw-r--r--src/pal/src/include/pal/shmemory.h331
-rw-r--r--src/pal/src/include/pal/stackstring.hpp239
-rw-r--r--src/pal/src/include/pal/synchcache.hpp397
-rw-r--r--src/pal/src/include/pal/synchobjects.hpp216
-rw-r--r--src/pal/src/include/pal/thread.hpp838
-rw-r--r--src/pal/src/include/pal/threadinfo.hpp89
-rw-r--r--src/pal/src/include/pal/threadsusp.hpp382
-rw-r--r--src/pal/src/include/pal/tls.hpp65
-rw-r--r--src/pal/src/include/pal/unicode_data.h69
-rw-r--r--src/pal/src/include/pal/utf8.h53
-rw-r--r--src/pal/src/include/pal/utils.h157
-rw-r--r--src/pal/src/include/pal/virtual.h208
51 files changed, 10585 insertions, 0 deletions
diff --git a/src/pal/src/include/pal/cert.hpp b/src/pal/src/include/pal/cert.hpp
new file mode 100644
index 0000000000..77c7f28d1a
--- /dev/null
+++ b/src/pal/src/include/pal/cert.hpp
@@ -0,0 +1,33 @@
+// 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:
+
+ include/pal/cert.hpp
+
+Abstract:
+ Header file for cert structures
+
+
+
+--*/
+
+#ifndef _PAL_CERT_HPP_
+#define _PAL_CERT_HPP_
+
+#include "corunix.hpp"
+
+#include <Security/Security.h>
+
+CorUnix::PAL_ERROR OIDToStr(CSSM_DATA &data, CHAR *&oidStrOut);
+
+CSSM_RETURN InitCSSMModule(const CSSM_GUID *inGuid, CSSM_SERVICE_TYPE inService,
+ CSSM_MODULE_HANDLE_PTR outModule);
+CSSM_RETURN TermCSSMModule(const CSSM_GUID *inGuid, CSSM_MODULE_HANDLE_PTR inModule);
+
+#endif // !_PAL_CERT_HPP_
diff --git a/src/pal/src/include/pal/context.h b/src/pal/src/include/pal/context.h
new file mode 100644
index 0000000000..5e378942fb
--- /dev/null
+++ b/src/pal/src/include/pal/context.h
@@ -0,0 +1,641 @@
+// 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:
+
+ include/pal/context.h
+
+Abstract:
+
+ Header file for thread context utility functions.
+
+
+
+--*/
+
+#ifndef _PAL_CONTEXT_H_
+#define _PAL_CONTEXT_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#include <signal.h>
+#include <pthread.h>
+
+#if !HAVE_MACH_EXCEPTIONS
+/* A type to wrap the native context type, which is ucontext_t on some
+ * platforms and another type elsewhere. */
+#if HAVE_UCONTEXT_T
+#include <ucontext.h>
+
+typedef ucontext_t native_context_t;
+#else // HAVE_UCONTEXT_T
+#error Native context type is not known on this platform!
+#endif // HAVE_UCONTEXT_T
+#else // !HAVE_MACH_EXCEPTIONS
+#include <mach/kern_return.h>
+#include <mach/mach_port.h>
+#endif // !HAVE_MACH_EXCEPTIONS else
+
+#if HAVE___GREGSET_T
+
+#ifdef BIT64
+#define MCREG_Rbx(mc) ((mc).__gregs[_REG_RBX])
+#define MCREG_Rcx(mc) ((mc).__gregs[_REG_RCX])
+#define MCREG_Rdx(mc) ((mc).__gregs[_REG_RDX])
+#define MCREG_Rsi(mc) ((mc).__gregs[_REG_RSI])
+#define MCREG_Rdi(mc) ((mc).__gregs[_REG_RDI])
+#define MCREG_Rbp(mc) ((mc).__gregs[_REG_RBP])
+#define MCREG_Rax(mc) ((mc).__gregs[_REG_RAX])
+#define MCREG_Rip(mc) ((mc).__gregs[_REG_RIP])
+#define MCREG_Rsp(mc) ((mc).__gregs[_REG_RSP])
+#define MCREG_SegCs(mc) ((mc).__gregs[_REG_CS])
+#define MCREG_SegSs(mc) ((mc).__gregs[_REG_SS])
+#define MCREG_R8(mc) ((mc).__gregs[_REG_R8])
+#define MCREG_R9(mc) ((mc).__gregs[_REG_R9])
+#define MCREG_R10(mc) ((mc).__gregs[_REG_R10])
+#define MCREG_R11(mc) ((mc).__gregs[_REG_R11])
+#define MCREG_R12(mc) ((mc).__gregs[_REG_R12])
+#define MCREG_R13(mc) ((mc).__gregs[_REG_R13])
+#define MCREG_R14(mc) ((mc).__gregs[_REG_R14])
+#define MCREG_R15(mc) ((mc).__gregs[_REG_R15])
+#define MCREG_EFlags(mc) ((mc).__gregs[_REG_RFLAGS])
+
+#define FPREG_Xmm(uc, index) *(M128A*)&(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_xmm[index])
+
+#define FPREG_St(uc, index) *(M128A*)&(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_87_ac[index])
+
+#define FPREG_ControlWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_cw)
+#define FPREG_StatusWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_sw)
+#define FPREG_TagWord(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_tw)
+#define FPREG_ErrorOffset(uc) (*(DWORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_ip))
+#define FPREG_ErrorSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_ip) + 2)
+#define FPREG_DataOffset(uc) (*(DWORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp))
+#define FPREG_DataSelector(uc) *((WORD*) &(((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_dp) + 2)
+#define FPREG_MxCsr(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr)
+#define FPREG_MxCsr_Mask(uc) (((struct fxsave*)(&(uc)->uc_mcontext.__fpregs))->fx_mxcsr_mask)
+
+#else // BIT64
+
+#define MCREG_Ebx(mc) ((mc).__gregs[_REG_EBX])
+#define MCREG_Ecx(mc) ((mc).__gregs[_REG_ECX])
+#define MCREG_Edx(mc) ((mc).__gregs[_REG_EDX])
+#define MCREG_Esi(mc) ((mc).__gregs[_REG_ESI])
+#define MCREG_Edi(mc) ((mc).__gregs[_REG_EDI])
+#define MCREG_Ebp(mc) ((mc).__gregs[_REG_EBP])
+#define MCREG_Eax(mc) ((mc).__gregs[_REG_EAX])
+#define MCREG_Eip(mc) ((mc).__gregs[_REG_EIP])
+#define MCREG_Esp(mc) ((mc).__gregs[_REG_ESP])
+#define MCREG_SegCs(mc) ((mc).__gregs[_REG_CS])
+#define MCREG_SegSs(mc) ((mc).__gregs[_REG_SS])
+#define MCREG_EFlags(mc) ((mc).__gregs[_REG_RFLAGS])
+
+#endif // BIT64
+
+#elif HAVE_GREGSET_T
+
+#ifdef BIT64
+#define MCREG_Rbx(mc) ((mc).gregs[REG_RBX])
+#define MCREG_Rcx(mc) ((mc).gregs[REG_RCX])
+#define MCREG_Rdx(mc) ((mc).gregs[REG_RDX])
+#define MCREG_Rsi(mc) ((mc).gregs[REG_RSI])
+#define MCREG_Rdi(mc) ((mc).gregs[REG_RDI])
+#define MCREG_Rbp(mc) ((mc).gregs[REG_RBP])
+#define MCREG_Rax(mc) ((mc).gregs[REG_RAX])
+#define MCREG_Rip(mc) ((mc).gregs[REG_RIP])
+#define MCREG_Rsp(mc) ((mc).gregs[REG_RSP])
+#define MCREG_SegCs(mc) (*(WORD*)&((mc).gregs[REG_CSGSFS]))
+#define MCREG_R8(mc) ((mc).gregs[REG_R8])
+#define MCREG_R9(mc) ((mc).gregs[REG_R9])
+#define MCREG_R10(mc) ((mc).gregs[REG_R10])
+#define MCREG_R11(mc) ((mc).gregs[REG_R11])
+#define MCREG_R12(mc) ((mc).gregs[REG_R12])
+#define MCREG_R13(mc) ((mc).gregs[REG_R13])
+#define MCREG_R14(mc) ((mc).gregs[REG_R14])
+#define MCREG_R15(mc) ((mc).gregs[REG_R15])
+
+#define FPREG_Fpstate(uc) ((uc)->uc_mcontext.fpregs)
+#define FPREG_Xmm(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->_xmm[index])
+
+#define FPREG_St(uc, index) *(M128A*)&(FPREG_Fpstate(uc)->_st[index])
+
+#define FPREG_ControlWord(uc) (FPREG_Fpstate(uc)->cwd)
+#define FPREG_StatusWord(uc) (FPREG_Fpstate(uc)->swd)
+#define FPREG_TagWord(uc) (FPREG_Fpstate(uc)->ftw)
+#define FPREG_ErrorOffset(uc) *(DWORD*)&(FPREG_Fpstate(uc)->rip)
+#define FPREG_ErrorSelector(uc) *(((WORD*)&(FPREG_Fpstate(uc)->rip)) + 2)
+#define FPREG_DataOffset(uc) *(DWORD*)&(FPREG_Fpstate(uc)->rdp)
+#define FPREG_DataSelector(uc) *(((WORD*)&(FPREG_Fpstate(uc)->rdp)) + 2)
+#define FPREG_MxCsr(uc) (FPREG_Fpstate(uc)->mxcsr)
+#define FPREG_MxCsr_Mask(uc) (FPREG_Fpstate(uc)->mxcr_mask)
+
+/////////////////////
+// Extended state
+
+inline _fpx_sw_bytes *FPREG_FpxSwBytes(const ucontext_t *uc)
+{
+ // Bytes 464..511 in the FXSAVE format are available for software to use for any purpose. In this case, they are used to
+ // indicate information about extended state.
+ _ASSERTE(reinterpret_cast<UINT8 *>(&FPREG_Fpstate(uc)->padding[12]) - reinterpret_cast<UINT8 *>(FPREG_Fpstate(uc)) == 464);
+
+ _ASSERTE(FPREG_Fpstate(uc) != nullptr);
+
+ return reinterpret_cast<_fpx_sw_bytes *>(&FPREG_Fpstate(uc)->padding[12]);
+}
+
+inline UINT32 FPREG_ExtendedSize(const ucontext_t *uc)
+{
+ _ASSERTE(FPREG_FpxSwBytes(uc)->magic1 == FP_XSTATE_MAGIC1);
+ return FPREG_FpxSwBytes(uc)->extended_size;
+}
+
+inline bool FPREG_HasExtendedState(const ucontext_t *uc)
+{
+ // See comments in /usr/include/x86_64-linux-gnu/asm/sigcontext.h for info on how to detect if extended state is present
+ static_assert_no_msg(FP_XSTATE_MAGIC2_SIZE == sizeof(UINT32));
+
+ if (FPREG_FpxSwBytes(uc)->magic1 != FP_XSTATE_MAGIC1)
+ {
+ return false;
+ }
+
+ UINT32 extendedSize = FPREG_ExtendedSize(uc);
+ if (extendedSize < sizeof(_xstate))
+ {
+ return false;
+ }
+
+ _ASSERTE(extendedSize >= FP_XSTATE_MAGIC2_SIZE);
+ return *reinterpret_cast<UINT32 *>(reinterpret_cast<UINT8 *>(FPREG_Fpstate(uc)) + (extendedSize - FP_XSTATE_MAGIC2_SIZE))
+ == FP_XSTATE_MAGIC2;
+}
+
+inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc)
+{
+ static_assert_no_msg(sizeof(reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space) == 16 * 16);
+ _ASSERTE(FPREG_HasExtendedState(uc));
+
+ return reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space;
+}
+
+/////////////////////
+
+#else // BIT64
+
+#define MCREG_Ebx(mc) ((mc).gregs[REG_EBX])
+#define MCREG_Ecx(mc) ((mc).gregs[REG_ECX])
+#define MCREG_Edx(mc) ((mc).gregs[REG_EDX])
+#define MCREG_Esi(mc) ((mc).gregs[REG_ESI])
+#define MCREG_Edi(mc) ((mc).gregs[REG_EDI])
+#define MCREG_Ebp(mc) ((mc).gregs[REG_EBP])
+#define MCREG_Eax(mc) ((mc).gregs[REG_EAX])
+#define MCREG_Eip(mc) ((mc).gregs[REG_EIP])
+#define MCREG_Esp(mc) ((mc).gregs[REG_ESP])
+#define MCREG_SegCs(mc) ((mc).gregs[REG_CS])
+#define MCREG_SegSs(mc) ((mc).gregs[REG_SS])
+
+#endif // BIT64
+
+#define MCREG_EFlags(mc) ((mc).gregs[REG_EFL])
+
+#else // HAVE_GREGSET_T
+
+#ifdef BIT64
+
+#if defined(_ARM64_)
+#define MCREG_X0(mc) ((mc).regs[0])
+#define MCREG_X1(mc) ((mc).regs[1])
+#define MCREG_X2(mc) ((mc).regs[2])
+#define MCREG_X3(mc) ((mc).regs[3])
+#define MCREG_X4(mc) ((mc).regs[4])
+#define MCREG_X5(mc) ((mc).regs[5])
+#define MCREG_X6(mc) ((mc).regs[6])
+#define MCREG_X7(mc) ((mc).regs[7])
+#define MCREG_X8(mc) ((mc).regs[8])
+#define MCREG_X9(mc) ((mc).regs[9])
+#define MCREG_X10(mc) ((mc).regs[10])
+#define MCREG_X11(mc) ((mc).regs[11])
+#define MCREG_X12(mc) ((mc).regs[12])
+#define MCREG_X13(mc) ((mc).regs[13])
+#define MCREG_X14(mc) ((mc).regs[14])
+#define MCREG_X15(mc) ((mc).regs[15])
+#define MCREG_X16(mc) ((mc).regs[16])
+#define MCREG_X17(mc) ((mc).regs[17])
+#define MCREG_X18(mc) ((mc).regs[18])
+#define MCREG_X19(mc) ((mc).regs[19])
+#define MCREG_X20(mc) ((mc).regs[20])
+#define MCREG_X21(mc) ((mc).regs[21])
+#define MCREG_X22(mc) ((mc).regs[22])
+#define MCREG_X23(mc) ((mc).regs[23])
+#define MCREG_X24(mc) ((mc).regs[24])
+#define MCREG_X25(mc) ((mc).regs[25])
+#define MCREG_X26(mc) ((mc).regs[26])
+#define MCREG_X27(mc) ((mc).regs[27])
+#define MCREG_X28(mc) ((mc).regs[28])
+#define MCREG_Fp(mc) ((mc).regs[29])
+#define MCREG_Lr(mc) ((mc).regs[30])
+
+#define MCREG_Sp(mc) ((mc).sp)
+#define MCREG_Pc(mc) ((mc).pc)
+#define MCREG_PState(mc) ((mc).pstate)
+#define MCREG_Cpsr(mc) ((mc).cpsr)
+#else
+ // For FreeBSD, as found in x86/ucontext.h
+#define MCREG_Rbp(mc) ((mc).mc_rbp)
+#define MCREG_Rip(mc) ((mc).mc_rip)
+#define MCREG_Rsp(mc) ((mc).mc_rsp)
+#define MCREG_Rsi(mc) ((mc).mc_rsi)
+#define MCREG_Rdi(mc) ((mc).mc_rdi)
+#define MCREG_Rbx(mc) ((mc).mc_rbx)
+#define MCREG_Rdx(mc) ((mc).mc_rdx)
+#define MCREG_Rcx(mc) ((mc).mc_rcx)
+#define MCREG_Rax(mc) ((mc).mc_rax)
+#define MCREG_R8(mc) ((mc).mc_r8)
+#define MCREG_R9(mc) ((mc).mc_r9)
+#define MCREG_R10(mc) ((mc).mc_r10)
+#define MCREG_R11(mc) ((mc).mc_r11)
+#define MCREG_R12(mc) ((mc).mc_r12)
+#define MCREG_R13(mc) ((mc).mc_r13)
+#define MCREG_R14(mc) ((mc).mc_r14)
+#define MCREG_R15(mc) ((mc).mc_r15)
+#define MCREG_EFlags(mc) ((mc).mc_rflags)
+#define MCREG_SegCs(mc) ((mc).mc_cs)
+
+ // from x86/fpu.h: struct __envxmm64
+#define FPSTATE(uc) ((savefpu*)((uc)->uc_mcontext.mc_fpstate))
+#define FPREG_ControlWord(uc) FPSTATE(uc)->sv_env.en_cw
+#define FPREG_StatusWord(uc) FPSTATE(uc)->sv_env.en_sw
+#define FPREG_TagWord(uc) FPSTATE(uc)->sv_env.en_tw
+#define FPREG_MxCsr(uc) FPSTATE(uc)->sv_env.en_mxcsr
+#define FPREG_MxCsr_Mask(uc) FPSTATE(uc)->sv_env.en_mxcsr_mask
+#define FPREG_ErrorOffset(uc) *(DWORD*) &(FPSTATE(uc)->sv_env.en_rip)
+#define FPREG_ErrorSelector(uc) *((WORD*) &(FPSTATE(uc)->sv_env.en_rip) + 2)
+#define FPREG_DataOffset(uc) *(DWORD*) &(FPSTATE(uc)->sv_env.en_rdp)
+#define FPREG_DataSelector(uc) *((WORD*) &(FPSTATE(uc)->sv_env.en_rdp) + 2)
+
+#define FPREG_Xmm(uc, index) *(M128A*) &(FPSTATE(uc)->sv_xmm[index])
+#define FPREG_St(uc, index) *(M128A*) &(FPSTATE(uc)->sv_fp[index].fp_acc)
+#endif
+
+#else // BIT64
+
+#if defined(_ARM_)
+
+#define MCREG_R0(mc) ((mc).arm_r0)
+#define MCREG_R1(mc) ((mc).arm_r1)
+#define MCREG_R2(mc) ((mc).arm_r2)
+#define MCREG_R3(mc) ((mc).arm_r3)
+#define MCREG_R4(mc) ((mc).arm_r4)
+#define MCREG_R5(mc) ((mc).arm_r5)
+#define MCREG_R6(mc) ((mc).arm_r6)
+#define MCREG_R7(mc) ((mc).arm_r7)
+#define MCREG_R8(mc) ((mc).arm_r8)
+#define MCREG_R9(mc) ((mc).arm_r9)
+#define MCREG_R10(mc) ((mc).arm_r10)
+#define MCREG_R11(mc) ((mc).arm_fp)
+#define MCREG_R12(mc) ((mc).arm_ip)
+#define MCREG_Sp(mc) ((mc).arm_sp)
+#define MCREG_Lr(mc) ((mc).arm_lr)
+#define MCREG_Pc(mc) ((mc).arm_pc)
+#define MCREG_Cpsr(mc) ((mc).arm_cpsr)
+
+#elif defined(_X86_)
+
+#define MCREG_Ebx(mc) ((mc).mc_ebx)
+#define MCREG_Ecx(mc) ((mc).mc_ecx)
+#define MCREG_Edx(mc) ((mc).mc_edx)
+#define MCREG_Esi(mc) ((mc).mc_esi)
+#define MCREG_Edi(mc) ((mc).mc_edi)
+#define MCREG_Ebp(mc) ((mc).mc_ebp)
+#define MCREG_Eax(mc) ((mc).mc_eax)
+#define MCREG_Eip(mc) ((mc).mc_eip)
+#define MCREG_SegCs(mc) ((mc).mc_cs)
+#define MCREG_EFlags(mc) ((mc).mc_eflags)
+#define MCREG_Esp(mc) ((mc).mc_esp)
+#define MCREG_SegSs(mc) ((mc).mc_ss)
+
+#else
+#error "Unsupported arch"
+#endif
+
+#endif // BIT64
+
+#endif // HAVE_GREGSET_T
+
+
+#if HAVE_PT_REGS
+
+#ifdef BIT64
+#define PTREG_Rbx(ptreg) ((ptreg).rbx)
+#define PTREG_Rcx(ptreg) ((ptreg).rcx)
+#define PTREG_Rdx(ptreg) ((ptreg).rdx)
+#define PTREG_Rsi(ptreg) ((ptreg).rsi)
+#define PTREG_Rdi(ptreg) ((ptreg).rdi)
+#define PTREG_Rbp(ptreg) ((ptreg).rbp)
+#define PTREG_Rax(ptreg) ((ptreg).rax)
+#define PTREG_Rip(ptreg) ((ptreg).rip)
+#define PTREG_SegCs(ptreg) ((ptreg).cs)
+#define PTREG_SegSs(ptreg) ((ptreg).ss)
+#define PTREG_Rsp(ptreg) ((ptreg).rsp)
+#define PTREG_R8(ptreg) ((ptreg).r8)
+#define PTREG_R9(ptreg) ((ptreg).r9)
+#define PTREG_R10(ptreg) ((ptreg).r10)
+#define PTREG_R11(ptreg) ((ptreg).r11)
+#define PTREG_R12(ptreg) ((ptreg).r12)
+#define PTREG_R13(ptreg) ((ptreg).r13)
+#define PTREG_R14(ptreg) ((ptreg).r14)
+#define PTREG_R15(ptreg) ((ptreg).r15)
+
+#else // BIT64
+
+#if defined(_ARM_)
+#define PTREG_R0(ptreg) ((ptreg).uregs[0])
+#define PTREG_R1(ptreg) ((ptreg).uregs[1])
+#define PTREG_R2(ptreg) ((ptreg).uregs[2])
+#define PTREG_R3(ptreg) ((ptreg).uregs[3])
+#define PTREG_R4(ptreg) ((ptreg).uregs[4])
+#define PTREG_R5(ptreg) ((ptreg).uregs[5])
+#define PTREG_R6(ptreg) ((ptreg).uregs[6])
+#define PTREG_R7(ptreg) ((ptreg).uregs[7])
+#define PTREG_R8(ptreg) ((ptreg).uregs[8])
+#define PTREG_R9(ptreg) ((ptreg).uregs[9])
+#define PTREG_R10(ptreg) ((ptreg).uregs[10])
+#define PTREG_R11(ptreg) ((ptreg).uregs[11])
+#define PTREG_R12(ptreg) ((ptreg).uregs[12])
+#define PTREG_Sp(ptreg) ((ptreg).uregs[13])
+#define PTREG_Lr(ptreg) ((ptreg).uregs[14])
+#define PTREG_Pc(ptreg) ((ptreg).uregs[15])
+#define PTREG_Cpsr(ptreg) ((ptreg).uregs[16])
+#elif defined(_X86_)
+#define PTREG_Ebx(ptreg) ((ptreg).ebx)
+#define PTREG_Ecx(ptreg) ((ptreg).ecx)
+#define PTREG_Edx(ptreg) ((ptreg).edx)
+#define PTREG_Esi(ptreg) ((ptreg).esi)
+#define PTREG_Edi(ptreg) ((ptreg).edi)
+#define PTREG_Ebp(ptreg) ((ptreg).ebp)
+#define PTREG_Eax(ptreg) ((ptreg).eax)
+#define PTREG_Eip(ptreg) ((ptreg).eip)
+#define PTREG_SegCs(ptreg) ((ptreg).xcs)
+#define PTREG_SegSs(ptreg) ((ptreg).xss)
+#define PTREG_Esp(ptreg) ((ptreg).esp)
+#else
+#error "Unsupported arch"
+#endif
+
+#endif // BIT64
+
+
+#define PTREG_EFlags(ptreg) ((ptreg).eflags)
+
+#endif // HAVE_PT_REGS
+
+
+
+#if HAVE_BSD_REGS_T
+
+#ifndef BSD_REGS_STYLE
+#error "struct reg" has unrecognized format
+#endif
+
+#ifdef BIT64
+
+#define BSDREG_Rbx(reg) BSD_REGS_STYLE(reg,RBX,rbx)
+#define BSDREG_Rcx(reg) BSD_REGS_STYLE(reg,RCX,rcx)
+#define BSDREG_Rdx(reg) BSD_REGS_STYLE(reg,RDX,rdx)
+#define BSDREG_Rsi(reg) BSD_REGS_STYLE(reg,RSI,rsi)
+#define BSDREG_Rdi(reg) BSD_REGS_STYLE(reg,RDI,rdi)
+#define BSDREG_Rbp(reg) BSD_REGS_STYLE(reg,RBP,rbp)
+#define BSDREG_Rax(reg) BSD_REGS_STYLE(reg,RAX,rax)
+#define BSDREG_Rip(reg) BSD_REGS_STYLE(reg,RIP,rip)
+#define BSDREG_SegCs(reg) BSD_REGS_STYLE(reg,CS,cs)
+#define BSDREG_SegSs(reg) BSD_REGS_STYLE(reg,SS,ss)
+#define BSDREG_Rsp(reg) BSD_REGS_STYLE(reg,RSP,rsp)
+#define BSDREG_R8(reg) BSD_REGS_STYLE(reg,R8,r8)
+#define BSDREG_R9(reg) BSD_REGS_STYLE(reg,R9,r9)
+#define BSDREG_R10(reg) BSD_REGS_STYLE(reg,R10,r10)
+#define BSDREG_R11(reg) BSD_REGS_STYLE(reg,R11,r11)
+#define BSDREG_R12(reg) BSD_REGS_STYLE(reg,R12,r12)
+#define BSDREG_R13(reg) BSD_REGS_STYLE(reg,R13,r13)
+#define BSDREG_R14(reg) BSD_REGS_STYLE(reg,R14,r14)
+#define BSDREG_R15(reg) BSD_REGS_STYLE(reg,R15,r15)
+#define BSDREG_EFlags(reg) BSD_REGS_STYLE(reg,RFLAGS,rflags)
+
+#else // BIT64
+
+#define BSDREG_Ebx(reg) BSD_REGS_STYLE(reg,EBX,ebx)
+#define BSDREG_Ecx(reg) BSD_REGS_STYLE(reg,ECX,ecx)
+#define BSDREG_Edx(reg) BSD_REGS_STYLE(reg,EDX,edx)
+#define BSDREG_Esi(reg) BSD_REGS_STYLE(reg,ESI,esi)
+#define BSDREG_Edi(reg) BSD_REGS_STYLE(reg,EDI,edi)
+#define BSDREG_Ebp(reg) BSD_REGS_STYLE(reg,EDP,ebp)
+#define BSDREG_Eax(reg) BSD_REGS_STYLE(reg,EAX,eax)
+#define BSDREG_Eip(reg) BSD_REGS_STYLE(reg,EIP,eip)
+#define BSDREG_SegCs(reg) BSD_REGS_STYLE(reg,CS,cs)
+#define BSDREG_EFlags(reg) BSD_REGS_STYLE(reg,EFLAGS,eflags)
+#define BSDREG_Esp(reg) BSD_REGS_STYLE(reg,ESP,esp)
+#define BSDREG_SegSs(reg) BSD_REGS_STYLE(reg,SS,ss)
+
+#endif // BIT64
+
+#endif // HAVE_BSD_REGS_T
+
+inline static DWORD64 CONTEXTGetPC(LPCONTEXT pContext)
+{
+#if defined(_AMD64_)
+ return pContext->Rip;
+#elif defined(_ARM64_) || defined(_ARM_)
+ return pContext->Pc;
+#else
+#error don't know how to get the program counter for this architecture
+#endif
+}
+
+inline static void CONTEXTSetPC(LPCONTEXT pContext, DWORD64 pc)
+{
+#if defined(_AMD64_)
+ pContext->Rip = pc;
+#elif defined(_ARM64_) || defined(_ARM_)
+ pContext->Pc = pc;
+#else
+#error don't know how to set the program counter for this architecture
+#endif
+}
+
+/*++
+Function :
+ CONTEXT_CaptureContext
+
+ Captures the context of the caller.
+ The returned context is suitable for performing
+ a virtual unwind.
+
+Parameters :
+ LPCONTEXT lpContext : new context
+
+--*/
+void
+CONTEXT_CaptureContext(
+ LPCONTEXT lpContext
+ );
+
+/*++
+Function :
+ CONTEXT_SetThreadContext
+
+ Processor-dependent implementation of SetThreadContext
+
+Parameters :
+ HANDLE hThread : thread whose context is to be set
+ CONTEXT *lpContext : new context
+
+Return value :
+ TRUE on success, FALSE on failure
+
+--*/
+BOOL
+CONTEXT_SetThreadContext(
+ DWORD dwProcessId,
+ pthread_t self,
+ CONST CONTEXT *lpContext
+ );
+
+/*++
+Function :
+ CONTEXT_GetThreadContext
+
+ Processor-dependent implementation of GetThreadContext
+
+Parameters :
+ HANDLE hThread : thread whose context is to retrieved
+ LPCONTEXT lpContext : destination for thread's context
+
+Return value :
+ TRUE on success, FALSE on failure
+
+--*/
+BOOL
+CONTEXT_GetThreadContext(
+ DWORD dwProcessId,
+ pthread_t self,
+ LPCONTEXT lpContext);
+
+#if HAVE_MACH_EXCEPTIONS
+/*++
+Function:
+ CONTEXT_GetThreadContextFromPort
+
+ Helper for GetThreadContext that uses a mach_port
+--*/
+kern_return_t
+CONTEXT_GetThreadContextFromPort(
+ mach_port_t Port,
+ LPCONTEXT lpContext);
+
+/*++
+Function:
+ SetThreadContextOnPort
+
+ Helper for CONTEXT_SetThreadContext
+--*/
+kern_return_t
+CONTEXT_SetThreadContextOnPort(
+ mach_port_t Port,
+ IN CONST CONTEXT *lpContext);
+
+/*++
+Function:
+ GetThreadContextFromThreadState
+
+ Helper for mach exception support
+--*/
+void
+CONTEXT_GetThreadContextFromThreadState(
+ thread_state_flavor_t stateFlavor,
+ thread_state_t threadState,
+ LPCONTEXT lpContext);
+
+#else // HAVE_MACH_EXCEPTIONS
+/*++
+Function :
+ CONTEXTToNativeContext
+
+ Converts a CONTEXT record to a native context.
+
+Parameters :
+ CONST CONTEXT *lpContext : CONTEXT to convert, including
+ flags that determine which registers are valid in
+ lpContext and which ones to set in native
+ native_context_t *native : native context to fill in
+
+Return value :
+ None
+
+--*/
+void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native);
+
+/*++
+Function :
+ CONTEXTFromNativeContext
+
+ Converts a native context to a CONTEXT record.
+
+Parameters :
+ const native_context_t *native : native context to convert
+ LPCONTEXT lpContext : CONTEXT to fill in
+ ULONG contextFlags : flags that determine which registers are valid in
+ native and which ones to set in lpContext
+
+Return value :
+ None
+
+--*/
+void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContext,
+ ULONG contextFlags);
+
+/*++
+Function :
+ GetNativeContextPC
+
+ Returns the program counter from the native context.
+
+Parameters :
+ const native_context_t *context : native context
+
+Return value :
+ The program counter from the native context.
+
+--*/
+LPVOID GetNativeContextPC(const native_context_t *context);
+
+/*++
+Function :
+ CONTEXTGetExceptionCodeForSignal
+
+ Translates signal and context information to a Win32 exception code.
+
+Parameters :
+ const siginfo_t *siginfo : signal information from a signal handler
+ const native_context_t *context : context information
+
+Return value :
+ The Win32 exception code that corresponds to the signal and context
+ information.
+
+--*/
+DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo,
+ const native_context_t *context);
+
+#endif // HAVE_MACH_EXCEPTIONS else
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _PAL_CONTEXT_H_
diff --git a/src/pal/src/include/pal/corunix.hpp b/src/pal/src/include/pal/corunix.hpp
new file mode 100644
index 0000000000..e9e9503ed3
--- /dev/null
+++ b/src/pal/src/include/pal/corunix.hpp
@@ -0,0 +1,1359 @@
+// 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:
+
+ corunix.hpp
+
+Abstract:
+
+ Internal interface and object definitions
+
+
+
+--*/
+
+#ifndef _CORUNIX_H
+#define _CORUNIX_H
+
+#include "palinternal.h"
+
+namespace CorUnix
+{
+ typedef DWORD PAL_ERROR;
+
+ //
+ // Forward declarations for classes defined in other headers
+ //
+
+ class CPalThread;
+
+ //
+ // Forward declarations for items in this header
+ //
+
+ class CObjectType;
+ class IPalObject;
+
+ //
+ // A simple counted string class. Using counted strings
+ // allows for some optimizations when searching for a matching string.
+ //
+
+ class CPalString
+ {
+ protected:
+
+ const WCHAR *m_pwsz; // NULL terminated
+
+ //
+ // Length of string, not including terminating NULL
+ //
+
+ DWORD m_dwStringLength;
+
+ //
+ // Length of buffer backing string; must be at least 1+dwStringLength
+ //
+
+ DWORD m_dwMaxLength;
+
+ public:
+
+ CPalString()
+ :
+ m_pwsz(NULL),
+ m_dwStringLength(0),
+ m_dwMaxLength(0)
+ {
+ };
+
+ CPalString(
+ const WCHAR *pwsz
+ )
+ {
+ SetString(pwsz);
+ };
+
+ void
+ SetString(
+ const WCHAR *pwsz
+ )
+ {
+ SetStringWithLength(pwsz, PAL_wcslen(pwsz));
+ };
+
+ void
+ SetStringWithLength(
+ const WCHAR *pwsz,
+ DWORD dwStringLength
+ )
+ {
+ m_pwsz = pwsz;
+ m_dwStringLength = dwStringLength;
+ m_dwMaxLength = m_dwStringLength + 1;
+
+ };
+
+ PAL_ERROR
+ CopyString(
+ CPalString *psSource
+ );
+
+ void
+ FreeBuffer();
+
+ const WCHAR *
+ GetString()
+ {
+ return m_pwsz;
+ };
+
+ DWORD
+ GetStringLength()
+ {
+ return m_dwStringLength;
+ };
+
+ DWORD
+ GetMaxLength()
+ {
+ return m_dwMaxLength;
+ };
+
+ };
+
+ //
+ // Signature of the cleanup routine that is to be called for an object
+ // type when:
+ // 1) The object's refcount drops to 0
+ // 2) A process is shutting down
+ // 3) A process has released all local references to the object
+ //
+ // The cleanup routine must only cleanup the object's shared state
+ // when the last parameter (fCleanupSharedSate) is TRUE. When
+ // fCleanupSharedState is FALSE the cleanup routine must not attempt
+ // to access the shared data for the object, as another process may
+ // have already deleted it. ($$REIVEW -- would someone ever need access
+ // to the shared data in order to cleanup process local state?)
+ //
+ // When the third paramter (fShutdown) is TRUE the process is in
+ // the act of exiting. The cleanup routine should not perform any
+ // unnecessary cleanup operations (e.g., closing file descriptors,
+ // since the OS will automatically close them when the process exits)
+ // in this situation.
+ //
+
+ typedef void (*OBJECTCLEANUPROUTINE) (
+ CPalThread *, // pThread
+ IPalObject *, // pObjectToCleanup
+ bool, // fShutdown
+ bool // fCleanupSharedState
+ );
+
+ //
+ // Signature of the initialization routine that is to be called
+ // when the first reference within a process to an existing
+ // object comes into existence. This routine is responsible for
+ // initializing the object's process local data, based on the
+ // immutable and shared data. The thread that this routine is
+ // called on holds an implicit read lock on the shared data.
+ //
+
+ typedef PAL_ERROR (*OBJECTINITROUTINE) (
+ CPalThread *, // pThread
+ CObjectType *, // pObjectType
+ void *, // pImmutableData
+ void *, // pSharedData
+ void * // pProcessLocalData
+ );
+
+ enum PalObjectTypeId
+ {
+ otiAutoResetEvent = 0,
+ otiManualResetEvent,
+ otiMutex,
+ otiNamedMutex,
+ otiSemaphore,
+ otiFile,
+ otiFileMapping,
+ otiSocket,
+ otiProcess,
+ otiThread,
+ otiIOCompletionPort,
+ ObjectTypeIdCount // This entry must come last in the enumeration
+ };
+
+ //
+ // There should be one instance of CObjectType for each supported
+ // type in a process; this allows for pointer equality tests
+ // to be used (though in general it's probably better to use
+ // checks based on the type ID). All members of this structure are
+ // immutable.
+ //
+ // The data size members control how much space will be allocated for
+ // instances of this object. Any or all of those members may be 0.
+ //
+ // dwSupportedAccessRights is the mask of valid access bits for this
+ // object type. Supported generic rights should not be included in
+ // this member.
+ //
+ // The generic access rights mapping (structure TBD) defines how the
+ // supported generic access rights (e.g., GENERIC_READ) map to the
+ // specific access rights for this object type.
+ //
+ // If instances of this object may have a security descriptor set on
+ // them eSecuritySupport should be set to SecuritySupported. If the OS can
+ // persist security information for the object type (as would be the case
+ // for, say, files) eSecurityPersistence should be set to
+ // OSPersistedSecurityInfo.
+ //
+ // If the object may have a name eObjectNameSupport should be
+ // ObjectCanHaveName. A named object can be opened in more than one
+ // process.
+ //
+ // If it is possible to duplicate a handle to an object across process
+ // boundaries then eHandleDuplicationSupport should be set to
+ // CrossProcessDuplicationAllowed. Note that it is possible to have
+ // an object type where eObjectNameSupport is ObjectCanHaveName and
+ // eHandleDuplicationSupport is LocalDuplicationOnly. For these object
+ // types an unnamed object instance will only have references from
+ // the creating process.
+ //
+ // If the object may be waited on eSynchronizationSupport should be
+ // WaitableObject. (Note that this implies that object type supports
+ // the SYNCHRONIZE access right.)
+ //
+ // The remaining members describe the wait-object semantics for the
+ // object type when eSynchronizationSupport is WaitableObject:
+ //
+ // * eSignalingSemantics: SingleTransitionObject for objects that, once
+ // they transition to the signaled state, can never transition back to
+ // the unsignaled state (e.g., processes and threads)
+ //
+ // * eThreadReleaseSemantics: if ThreadReleaseAltersSignalCount the object's
+ // signal count is decremented when a waiting thread is released; otherwise,
+ // the signal count is not modified (as is desired for a manual reset event).
+ // Must be ThreadReleaseHasNoSideEffects if eSignalingSemantics is
+ // SingleTransitionObject
+ //
+ // * eOwnershipSemantics: OwnershipTracked only for mutexes, for which the
+ // previous two items must also ObjectCanBeUnsignaled and
+ // ThreadReleaseAltersSignalCount.
+ //
+
+ class CObjectType
+ {
+ public:
+
+ enum SecuritySupport
+ {
+ SecuritySupported,
+ SecurityNotSupported
+ };
+
+ enum SecurityPersistence
+ {
+ OSPersistedSecurityInfo,
+ SecurityInfoNotPersisted
+ };
+
+ enum ObjectNameSupport
+ {
+ ObjectCanHaveName,
+ UnnamedObject
+ };
+
+ enum HandleDuplicationSupport
+ {
+ CrossProcessDuplicationAllowed,
+ LocalDuplicationOnly
+ };
+
+ enum SynchronizationSupport
+ {
+ WaitableObject,
+ UnwaitableObject
+ };
+
+ enum SignalingSemantics
+ {
+ ObjectCanBeUnsignaled,
+ SingleTransitionObject,
+ SignalingNotApplicable
+ };
+
+ enum ThreadReleaseSemantics
+ {
+ ThreadReleaseAltersSignalCount,
+ ThreadReleaseHasNoSideEffects,
+ ThreadReleaseNotApplicable
+ };
+
+ enum OwnershipSemantics
+ {
+ OwnershipTracked,
+ NoOwner,
+ OwnershipNotApplicable
+ };
+
+ private:
+
+ //
+ // Array that maps object type IDs to the corresponding
+ // CObjectType instance
+ //
+
+ static CObjectType* s_rgotIdMapping[];
+
+ PalObjectTypeId m_eTypeId;
+ OBJECTCLEANUPROUTINE m_pCleanupRoutine;
+ OBJECTINITROUTINE m_pInitRoutine;
+ DWORD m_dwImmutableDataSize;
+ DWORD m_dwProcessLocalDataSize;
+ DWORD m_dwSharedDataSize;
+ DWORD m_dwSupportedAccessRights;
+ // Generic access rights mapping
+ SecuritySupport m_eSecuritySupport;
+ SecurityPersistence m_eSecurityPersistence;
+ ObjectNameSupport m_eObjectNameSupport;
+ HandleDuplicationSupport m_eHandleDuplicationSupport;
+ SynchronizationSupport m_eSynchronizationSupport;
+ SignalingSemantics m_eSignalingSemantics;
+ ThreadReleaseSemantics m_eThreadReleaseSemantics;
+ OwnershipSemantics m_eOwnershipSemantics;
+
+ public:
+
+ CObjectType(
+ PalObjectTypeId eTypeId,
+ OBJECTCLEANUPROUTINE pCleanupRoutine,
+ OBJECTINITROUTINE pInitRoutine,
+ DWORD dwImmutableDataSize,
+ DWORD dwProcessLocalDataSize,
+ DWORD dwSharedDataSize,
+ DWORD dwSupportedAccessRights,
+ SecuritySupport eSecuritySupport,
+ SecurityPersistence eSecurityPersistence,
+ ObjectNameSupport eObjectNameSupport,
+ HandleDuplicationSupport eHandleDuplicationSupport,
+ SynchronizationSupport eSynchronizationSupport,
+ SignalingSemantics eSignalingSemantics,
+ ThreadReleaseSemantics eThreadReleaseSemantics,
+ OwnershipSemantics eOwnershipSemantics
+ )
+ :
+ m_eTypeId(eTypeId),
+ m_pCleanupRoutine(pCleanupRoutine),
+ m_pInitRoutine(pInitRoutine),
+ m_dwImmutableDataSize(dwImmutableDataSize),
+ m_dwProcessLocalDataSize(dwProcessLocalDataSize),
+ m_dwSharedDataSize(dwSharedDataSize),
+ m_dwSupportedAccessRights(dwSupportedAccessRights),
+ m_eSecuritySupport(eSecuritySupport),
+ m_eSecurityPersistence(eSecurityPersistence),
+ m_eObjectNameSupport(eObjectNameSupport),
+ m_eHandleDuplicationSupport(eHandleDuplicationSupport),
+ m_eSynchronizationSupport(eSynchronizationSupport),
+ m_eSignalingSemantics(eSignalingSemantics),
+ m_eThreadReleaseSemantics(eThreadReleaseSemantics),
+ m_eOwnershipSemantics(eOwnershipSemantics)
+ {
+ s_rgotIdMapping[eTypeId] = this;
+ };
+
+ static
+ CObjectType *
+ GetObjectTypeById(
+ PalObjectTypeId otid
+ )
+ {
+ return s_rgotIdMapping[otid];
+ };
+
+ PalObjectTypeId
+ GetId(
+ void
+ )
+ {
+ return m_eTypeId;
+ };
+
+ OBJECTCLEANUPROUTINE
+ GetObjectCleanupRoutine(
+ void
+ )
+ {
+ return m_pCleanupRoutine;
+ };
+
+ OBJECTINITROUTINE
+ GetObjectInitRoutine(
+ void
+ )
+ {
+ return m_pInitRoutine;
+ };
+
+ DWORD
+ GetImmutableDataSize(
+ void
+ )
+ {
+ return m_dwImmutableDataSize;
+ };
+
+ DWORD
+ GetProcessLocalDataSize(
+ void
+ )
+ {
+ return m_dwProcessLocalDataSize;
+ };
+
+ DWORD
+ GetSharedDataSize(
+ void
+ )
+ {
+ return m_dwSharedDataSize;
+ };
+
+ DWORD
+ GetSupportedAccessRights(
+ void
+ )
+ {
+ return m_dwSupportedAccessRights;
+ };
+
+ // Generic access rights mapping
+
+ SecuritySupport
+ GetSecuritySupport(
+ void
+ )
+ {
+ return m_eSecuritySupport;
+ };
+
+ SecurityPersistence
+ GetSecurityPersistence(
+ void
+ )
+ {
+ return m_eSecurityPersistence;
+ };
+
+ ObjectNameSupport
+ GetObjectNameSupport(
+ void
+ )
+ {
+ return m_eObjectNameSupport;
+ };
+
+ HandleDuplicationSupport
+ GetHandleDuplicationSupport(
+ void
+ )
+ {
+ return m_eHandleDuplicationSupport;
+ };
+
+ SynchronizationSupport
+ GetSynchronizationSupport(
+ void
+ )
+ {
+ return m_eSynchronizationSupport;
+ };
+
+ SignalingSemantics
+ GetSignalingSemantics(
+ void
+ )
+ {
+ return m_eSignalingSemantics;
+ };
+
+ ThreadReleaseSemantics
+ GetThreadReleaseSemantics(
+ void
+ )
+ {
+ return m_eThreadReleaseSemantics;
+ };
+
+ OwnershipSemantics
+ GetOwnershipSemantics(
+ void
+ )
+ {
+ return m_eOwnershipSemantics;
+ };
+ };
+
+ class CAllowedObjectTypes
+ {
+ private:
+
+ bool m_rgfAllowedTypes[ObjectTypeIdCount];
+
+ public:
+
+ bool
+ IsTypeAllowed(PalObjectTypeId eTypeId);
+
+ //
+ // Constructor for multiple allowed types
+ //
+
+ CAllowedObjectTypes(
+ PalObjectTypeId rgAllowedTypes[],
+ DWORD dwAllowedTypeCount
+ );
+
+ //
+ // Single allowed type constructor
+ //
+
+ CAllowedObjectTypes(
+ PalObjectTypeId eAllowedType
+ );
+
+ //
+ // Allow all types or no types constructor
+ //
+
+ CAllowedObjectTypes(
+ bool fAllowAllObjectTypes
+ )
+ {
+ for (DWORD dw = 0; dw < ObjectTypeIdCount; dw += 1)
+ {
+ m_rgfAllowedTypes[dw] = fAllowAllObjectTypes;
+ }
+ };
+
+ ~CAllowedObjectTypes()
+ {
+ };
+ };
+
+ //
+ // Attributes for a given object instance. If the object does not have
+ // a name the sObjectName member should be zero'd out. If the default
+ // security attributes are desired then pSecurityAttributes should
+ // be NULL.
+ //
+
+ class CObjectAttributes
+ {
+ public:
+
+ CPalString sObjectName;
+ LPSECURITY_ATTRIBUTES pSecurityAttributes;
+
+ CObjectAttributes(
+ const WCHAR *pwszObjectName,
+ LPSECURITY_ATTRIBUTES pSecurityAttributes_
+ )
+ :
+ pSecurityAttributes(pSecurityAttributes_)
+ {
+ if (NULL != pwszObjectName)
+ {
+ sObjectName.SetString(pwszObjectName);
+ }
+ };
+
+ CObjectAttributes()
+ :
+ pSecurityAttributes(NULL)
+ {
+ };
+ };
+
+ //
+ // ISynchStateController is used to modify any object's synchronization
+ // state. It is intended to be used from within the APIs exposed for
+ // various objects (e.g., SetEvent, ReleaseMutex, etc.).
+ //
+ // Each ISynchStateController instance implicitly holds what should be
+ // viewed as the global dispatcher lock, and as such should be released
+ // as quickly as possible. An ISynchStateController instance is bound to
+ // the thread that requested it; it may not be passed to a different
+ // thread.
+ //
+
+ class ISynchStateController
+ {
+ public:
+
+ virtual
+ PAL_ERROR
+ GetSignalCount(
+ LONG *plSignalCount
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ SetSignalCount(
+ LONG lNewCount
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ IncrementSignalCount(
+ LONG lAmountToIncrement
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ DecrementSignalCount(
+ LONG lAmountToDecrement
+ ) = 0;
+
+ //
+ // The following two routines may only be used for object types
+ // where eOwnershipSemantics is OwnershipTracked (i.e., mutexes).
+ //
+
+ //
+ // SetOwner is intended to be used in the implementation of
+ // CreateMutex when bInitialOwner is TRUE. It must be called
+ // before the new object instance is registered with the
+ // handle manager. Any other call to this method is an error.
+ //
+
+ virtual
+ PAL_ERROR
+ SetOwner(
+ CPalThread *pNewOwningThread
+ ) = 0;
+
+ //
+ // DecrementOwnershipCount returns an error if the object
+ // is unowned, or if the thread this controller is bound to
+ // is not the owner of the object.
+ //
+
+ virtual
+ PAL_ERROR
+ DecrementOwnershipCount(
+ void
+ ) = 0;
+
+ virtual
+ void
+ ReleaseController(
+ void
+ ) = 0;
+ };
+
+ //
+ // ISynchWaitController is used to indicate a thread's desire to wait for
+ // an object (which possibly includes detecting instances where the wait
+ // can be satisfied without blocking). It is intended to be used by object
+ // wait function (WaitForSingleObject, etc.).
+ //
+ // Each ISynchWaitController instance implicitly holds what should be
+ // viewed as the global dispatcher lock, and as such should be released
+ // as quickly as possible. An ISynchWaitController instance is bound to
+ // the thread that requested it; it may not be passed to a different
+ // thread.
+ //
+ // A thread may hold multiple ISynchWaitController instances
+ // simultaneously.
+ //
+
+ enum WaitType
+ {
+ SingleObject,
+ MultipleObjectsWaitOne,
+ MultipleObjectsWaitAll
+ };
+
+ class ISynchWaitController
+ {
+ public:
+
+ //
+ // CanThreadWaitWithoutBlocking informs the caller if a wait
+ // operation may succeed immediately, but does not actually
+ // alter any object state. ReleaseWaitingThreadWithoutBlocking
+ // alters the object state, and will return an error if it is
+ // not possible for the wait to be immediately satisfied.
+ //
+
+ virtual
+ PAL_ERROR
+ CanThreadWaitWithoutBlocking(
+ bool *pfCanWaitWithoutBlocking, // OUT
+ bool *pfAbandoned
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ ReleaseWaitingThreadWithoutBlocking(
+ ) = 0;
+
+ //
+ // dwIndex is intended for MultipleObjectsWaitOne situations. The
+ // index for the object that becomes signaled and satisfies the
+ // wait will be returned in the call to BlockThread.
+ //
+
+ virtual
+ PAL_ERROR
+ RegisterWaitingThread(
+ WaitType eWaitType,
+ DWORD dwIndex,
+ bool fAltertable
+ ) = 0;
+
+ //
+ // Why is there no unregister waiting thread routine? Unregistration
+ // is the responsibility of the synchronization provider, not the
+ // implementation of the wait object routines. (I can be convinced
+ // that this isn't the best approach, though...)
+ //
+
+ virtual
+ void
+ ReleaseController(
+ void
+ ) = 0;
+ };
+
+ enum LockType
+ {
+ ReadLock,
+ WriteLock
+ };
+
+ class IDataLock
+ {
+ public:
+
+ //
+ // If a thread obtains a write lock but does not actually
+ // modify any data it should set fDataChanged to FALSE. If
+ // a thread obtain a read lock and does actually modify any
+ // data it should be taken out back and shot.
+ //
+
+ virtual
+ void
+ ReleaseLock(
+ CPalThread *pThread, // IN, OPTIONAL
+ bool fDataChanged
+ ) = 0;
+ };
+
+ //
+ // The following two enums are part of the local object
+ // optimizations
+ //
+
+ enum ObjectDomain
+ {
+ ProcessLocalObject,
+ SharedObject
+ };
+
+ enum WaitDomain
+ {
+ LocalWait, // All objects in the wait set are local to this process
+ MixedWait, // Some objects are local; some are shared
+ SharedWait // All objects in the wait set are shared
+ };
+
+ class IPalObject
+ {
+ public:
+
+ virtual
+ CObjectType *
+ GetObjectType(
+ VOID
+ ) = 0;
+
+ virtual
+ CObjectAttributes *
+ GetObjectAttributes(
+ VOID
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ GetImmutableData(
+ void **ppvImmutableData // OUT
+ ) = 0;
+
+ //
+ // The following two routines obtain either a read or write
+ // lock on the data in question. If a thread needs to examine
+ // both process-local and shared data simultaneously it must obtain
+ // the shared data first. A thread may not hold data locks
+ // on two different objects at the same time.
+ //
+
+ virtual
+ PAL_ERROR
+ GetProcessLocalData(
+ CPalThread *pThread, // IN, OPTIONAL
+ LockType eLockRequest,
+ IDataLock **ppDataLock, // OUT
+ void **ppvProcessLocalData // OUT
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ GetSharedData(
+ CPalThread *pThread, // IN, OPTIONAL
+ LockType eLockRequest,
+ IDataLock **ppDataLock, // OUT
+ void **ppvSharedData // OUT
+ ) = 0;
+
+ //
+ // The following two routines obtain the global dispatcher lock.
+ // If a thread needs to make use of a synchronization interface
+ // and examine object data it must obtain the synchronization
+ // interface first. A thread is allowed to hold synchronization
+ // interfaces for multiple objects at the same time if it obtains
+ // all of the interfaces through a single call (see IPalSynchronizationManager
+ // below).
+ //
+ // The single-call restriction allows the underlying implementation
+ // to possibly segement the global dispatcher lock. If this restriction
+ // were not in place (i.e., if a single thread were allowed to call
+ // GetSynchXXXController for multiple objects) no such segmentation
+ // would be possible as there would be no way know in what order a
+ // thread would choose to obtain the controllers.
+ //
+ // Note: this design precludes simultaneous acquisition of both
+ // the state and wait controller for an object but there are
+ // currently no places where doing so would be necessary.
+ //
+
+ virtual
+ PAL_ERROR
+ GetSynchStateController(
+ CPalThread *pThread, // IN, OPTIONAL
+ ISynchStateController **ppStateController // OUT
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ GetSynchWaitController(
+ CPalThread *pThread, // IN, OPTIONAL
+ ISynchWaitController **ppWaitController // OUT
+ ) = 0;
+
+ virtual
+ DWORD
+ AddReference(
+ void
+ ) = 0;
+
+ virtual
+ DWORD
+ ReleaseReference(
+ CPalThread *pThread
+ ) = 0;
+
+ //
+ // This routine is mainly intended for the synchronization
+ // manager. The promotion / process synch lock must be held
+ // before calling this routine.
+ //
+
+ virtual
+ ObjectDomain
+ GetObjectDomain(
+ void
+ ) = 0;
+
+ //
+ // This routine is only for use by the synchronization manager
+ // (specifically, for GetSynch*ControllersForObjects). The
+ // caller must have acquired the appropriate lock before
+ // (whatever exactly that must be) before calling this routine.
+ //
+
+ virtual
+ PAL_ERROR
+ GetObjectSynchData(
+ VOID **ppvSynchData // OUT
+ ) = 0;
+
+ };
+
+ class IPalProcess
+ {
+ public:
+ virtual
+ DWORD
+ GetProcessID(
+ void
+ ) = 0;
+ };
+
+ class IPalObjectManager
+ {
+ public:
+
+ //
+ // Object creation (e.g., what is done by CreateEvent) is a two step
+ // process. First, the new object is allocated and the initial
+ // properties set (e.g., initially signaled). Next, the object is
+ // registered, yielding a handle. If an object of the same name
+ // and appropriate type already existed the returned handle will refer
+ // to the previously existing object, and the newly allocated object
+ // will have been thrown away.
+ //
+ // (The two phase process minimizes the amount of time that any
+ // namespace locks need to be held. While some wasted work may be
+ // done in the existing object case that work only impacts the calling
+ // thread. Checking first for existence and then allocating and
+ // initializing on failure requires any namespace lock to be held for
+ // a much longer period of time, impacting the entire system.)
+ //
+
+ virtual
+ PAL_ERROR
+ AllocateObject(
+ CPalThread *pThread, // IN, OPTIONAL
+ CObjectType *pType,
+ CObjectAttributes *pAttributes,
+ IPalObject **ppNewObject // OUT
+ ) = 0;
+
+ //
+ // After calling RegisterObject pObjectToRegister is no
+ // longer valid. If successful there are two references
+ // on the returned object -- one for the handle, and one
+ // for the instance returned in ppRegisteredObject. The
+ // caller, therefore, is responsible for releasing the
+ // latter.
+ //
+ // For named object pAllowedTypes specifies what type of
+ // existing objects can be returned in ppRegisteredObjects.
+ // This is primarily intended for CreateEvent, so that
+ // a ManualResetEvent can be returned when attempting to
+ // register an AutoResetEvent (and vice-versa). pAllowedTypes
+ // must include the type of pObjectToRegister.
+ //
+
+ virtual
+ PAL_ERROR
+ RegisterObject(
+ CPalThread *pThread, // IN, OPTIONAL
+ IPalObject *pObjectToRegister,
+ CAllowedObjectTypes *pAllowedTypes,
+ DWORD dwRightsRequested,
+ HANDLE *pHandle, // OUT
+ IPalObject **ppRegisteredObject // OUT
+ ) = 0;
+
+ //
+ // LocateObject is used for OpenXXX routines. ObtainHandleForObject
+ // is needed for the OpenXXX routines and DuplicateHandle.
+ //
+
+ virtual
+ PAL_ERROR
+ LocateObject(
+ CPalThread *pThread, // IN, OPTIONAL
+ CPalString *psObjectToLocate,
+ CAllowedObjectTypes *pAllowedTypes,
+ IPalObject **ppObject // OUT
+ ) = 0;
+
+ //
+ // pProcessForHandle is to support cross-process handle
+ // duplication. It only needs to be specified when acquiring
+ // a handle meant for use in a different process; it should
+ // be left NULL when acquiring a handle for the current
+ // process.
+ //
+
+ virtual
+ PAL_ERROR
+ ObtainHandleForObject(
+ CPalThread *pThread, // IN, OPTIONAL
+ IPalObject *pObject,
+ DWORD dwRightsRequested,
+ bool fInheritHandle,
+ IPalProcess *pProcessForHandle, // IN, OPTIONAL
+ HANDLE *pNewHandle // OUT
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ RevokeHandle(
+ CPalThread *pThread, // IN, OPTIONAL
+ HANDLE hHandleToRevoke
+ ) = 0;
+
+ //
+ // The Reference routines are called to obtain the
+ // object that a handle refers to. The caller must
+ // specify the rights that the handle must hold for
+ // the operation that it is about to perform. The caller
+ // is responsible for converting generic rights to specific
+ // rights. The caller must also specify what object types
+ // are permissible for the object.
+ //
+ // The returned object[s], on success, are referenced,
+ // and the caller is responsible for releasing those references
+ // when appropriate.
+ //
+
+ virtual
+ PAL_ERROR
+ ReferenceObjectByHandle(
+ CPalThread *pThread, // IN, OPTIONAL
+ HANDLE hHandleToReference,
+ CAllowedObjectTypes *pAllowedTypes,
+ DWORD dwRightsRequired,
+ IPalObject **ppObject // OUT
+ ) = 0;
+
+ //
+ // This routine is intended for WaitForMultipleObjects[Ex]
+ //
+
+ virtual
+ PAL_ERROR
+ ReferenceMultipleObjectsByHandleArray(
+ CPalThread *pThread, // IN, OPTIONAL
+ HANDLE rghHandlesToReference[],
+ DWORD dwHandleCount,
+ CAllowedObjectTypes *pAllowedTypes,
+ DWORD dwRightsRequired,
+ IPalObject *rgpObjects[] // OUT
+ ) = 0;
+
+ //
+ // This routine is for cross-process handle duplication.
+ //
+
+ virtual
+ PAL_ERROR
+ ReferenceObjectByForeignHandle(
+ CPalThread *pThread, // IN, OPTIONAL
+ HANDLE hForeignHandle,
+ IPalProcess *pForeignProcess,
+ CAllowedObjectTypes *pAllowedTypes,
+ DWORD dwRightsRequired,
+ IPalObject **ppObject // OUT
+ ) = 0;
+
+ };
+
+ extern IPalObjectManager *g_pObjectManager;
+
+ enum ThreadWakeupReason
+ {
+ WaitSucceeded,
+ Alerted,
+ MutexAbondoned,
+ WaitTimeout,
+ WaitFailed
+ };
+
+ class IPalSynchronizationManager
+ {
+ public:
+
+ //
+ // A thread calls BlockThread to put itself to sleep after it has
+ // registered itself with the objects it is to wait on. A thread
+ // need not have registered with any objects, as would occur in
+ // the implementation of Sleep[Ex].
+ //
+ // Needless to say a thread must not be holding any PAL locks
+ // directly or implicitly (e.g., by holding a reference to a
+ // synchronization controller) when it calls this method.
+ //
+
+ virtual
+ PAL_ERROR
+ BlockThread(
+ CPalThread *pCurrentThread,
+ DWORD dwTimeout,
+ bool fAlertable,
+ bool fIsSleep,
+ ThreadWakeupReason *peWakeupReason, // OUT
+ DWORD *pdwSignaledObject // OUT
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ AbandonObjectsOwnedByThread(
+ CPalThread *pCallingThread,
+ CPalThread *pTargetThread
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ QueueUserAPC(
+ CPalThread *pThread,
+ CPalThread *pTargetThread,
+ PAPCFUNC pfnAPC,
+ ULONG_PTR dwData
+ ) = 0;
+
+ virtual
+ bool
+ AreAPCsPending(
+ CPalThread *pThread
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ DispatchPendingAPCs(
+ CPalThread *pThread
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ SendTerminationRequestToWorkerThread() = 0;
+
+ //
+ // This routine is primarily meant for use by WaitForMultipleObjects[Ex].
+ // The caller must individually release each of the returned controller
+ // interfaces.
+ //
+
+ virtual
+ PAL_ERROR
+ GetSynchWaitControllersForObjects(
+ CPalThread *pThread,
+ IPalObject *rgObjects[],
+ DWORD dwObjectCount,
+ ISynchWaitController *rgControllers[]
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ GetSynchStateControllersForObjects(
+ CPalThread *pThread,
+ IPalObject *rgObjects[],
+ DWORD dwObjectCount,
+ ISynchStateController *rgControllers[]
+ ) = 0;
+
+ //
+ // These following routines are meant for use only by IPalObject
+ // implementations. The first two routines are used to
+ // allocate and free an object's synchronization state; the third
+ // is called during object promotion.
+ //
+
+ virtual
+ PAL_ERROR
+ AllocateObjectSynchData(
+ CObjectType *pObjectType,
+ ObjectDomain eObjectDomain,
+ VOID **ppvSynchData // OUT
+ ) = 0;
+
+ virtual
+ void
+ FreeObjectSynchData(
+ CObjectType *pObjectType,
+ ObjectDomain eObjectDomain,
+ VOID *pvSynchData
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ PromoteObjectSynchData(
+ CPalThread *pThread,
+ VOID *pvLocalSynchData,
+ VOID **ppvSharedSynchData // OUT
+ ) = 0;
+
+ //
+ // The next two routines provide access to the process-wide
+ // synchronization lock
+ //
+
+ virtual
+ void
+ AcquireProcessLock(
+ CPalThread *pThread
+ ) = 0;
+
+ virtual
+ void
+ ReleaseProcessLock(
+ CPalThread *pThread
+ ) = 0;
+
+ //
+ // The final routines are used by IPalObject::GetSynchStateController
+ // and IPalObject::GetSynchWaitController
+ //
+
+ virtual
+ PAL_ERROR
+ CreateSynchStateController(
+ CPalThread *pThread, // IN, OPTIONAL
+ CObjectType *pObjectType,
+ VOID *pvSynchData,
+ ObjectDomain eObjectDomain,
+ ISynchStateController **ppStateController // OUT
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ CreateSynchWaitController(
+ CPalThread *pThread, // IN, OPTIONAL
+ CObjectType *pObjectType,
+ VOID *pvSynchData,
+ ObjectDomain eObjectDomain,
+ ISynchWaitController **ppWaitController // OUT
+ ) = 0;
+ };
+
+ extern IPalSynchronizationManager *g_pSynchronizationManager;
+
+ class IFileTransactionLock
+ {
+ public:
+
+ //
+ // Called when the transaction completes (which includes
+ // error completions, or the outright failure to queue
+ // the transaction).
+ //
+
+ virtual
+ void
+ ReleaseLock() = 0;
+ };
+
+ class IFileLockController
+ {
+ public:
+
+ //
+ // A transaction lock is acquired before a read or write
+ // operation, and released when that operation completes.
+ // The lock is not tied to the calling thread, since w/
+ // asynch file IO the completion may occur on a different
+ // thread.
+ //
+
+ enum FileTransactionLockType
+ {
+ ReadLock,
+ WriteLock
+ };
+
+ virtual
+ PAL_ERROR
+ GetTransactionLock(
+ CPalThread *pThread, // IN, OPTIONAL
+ FileTransactionLockType eLockType,
+ DWORD dwOffsetLow,
+ DWORD dwOffsetHigh,
+ DWORD nNumberOfBytesToLockLow,
+ DWORD nNumberOfBytesToLockHigh,
+ IFileTransactionLock **ppTransactionLock // OUT
+ ) = 0;
+
+ enum FileLockExclusivity
+ {
+ ExclusiveFileLock,
+ SharedFileLock
+ };
+
+ enum FileLockWaitMode
+ {
+ FailImmediately,
+ WaitForLockAcquisition
+ };
+
+ virtual
+ PAL_ERROR
+ CreateFileLock(
+ CPalThread *pThread, // IN, OPTIONAL
+ DWORD dwOffsetLow,
+ DWORD dwOffsetHigh,
+ DWORD nNumberOfBytesToLockLow,
+ DWORD nNumberOfBytesToLockHigh,
+ FileLockExclusivity eFileLockExclusivity,
+ FileLockWaitMode eFileLockWaitMode
+ ) = 0;
+
+ virtual
+ PAL_ERROR
+ ReleaseFileLock(
+ CPalThread *pThread, // IN, OPTIONAL
+ DWORD dwOffsetLow,
+ DWORD dwOffsetHigh,
+ DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh
+ ) = 0;
+
+ //
+ // ReleaseController should be called from the file object's
+ // cleanup routine. It must always be called, even if fShutdown is
+ // TRUE or fCleanupSharedState is FALSE.
+ //
+
+ virtual
+ void
+ ReleaseController() = 0;
+ };
+
+ class IFileLockManager
+ {
+ public:
+
+ //
+ // GetLockControllerForFile should be called by CreateFile.
+ // It will fail if the requested access rights and share
+ // mode are not compatible with existing lock controllers
+ // for the file.
+ //
+
+ virtual
+ PAL_ERROR
+ GetLockControllerForFile(
+ CPalThread *pThread, // IN, OPTIONAL
+ LPCSTR szFileName,
+ DWORD dwAccessRights,
+ DWORD dwShareMode,
+ IFileLockController **ppLockController // OUT
+ ) = 0;
+
+ //
+ // Gets the share mode for the file
+ // (returns SHARE_MODE_NOT_INITIALIZED if file lock controller
+ // not found)
+ //
+ virtual
+ PAL_ERROR
+ GetFileShareModeForFile(
+ LPCSTR szFileName,
+ DWORD* pdwShareMode) = 0;
+ };
+
+ extern IFileLockManager *g_pFileLockManager;
+}
+
+#endif // _CORUNIX_H
+
diff --git a/src/pal/src/include/pal/corunix.inl b/src/pal/src/include/pal/corunix.inl
new file mode 100644
index 0000000000..ab0ac70462
--- /dev/null
+++ b/src/pal/src/include/pal/corunix.inl
@@ -0,0 +1,55 @@
+// 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:
+
+
+
+--*/
+
+#ifndef _CORUNIX_INL
+#define _CORUNIX_INL
+
+#include "corunix.hpp"
+#include "dbgmsg.h"
+
+namespace CorUnix
+{
+
+ bool CAllowedObjectTypes::IsTypeAllowed(PalObjectTypeId eTypeId)
+ {
+ _ASSERTE(eTypeId != ObjectTypeIdCount);
+ return m_rgfAllowedTypes[eTypeId];
+ };
+
+ CAllowedObjectTypes::CAllowedObjectTypes(
+ PalObjectTypeId rgAllowedTypes[],
+ DWORD dwAllowedTypeCount
+ )
+ {
+ ZeroMemory(m_rgfAllowedTypes, sizeof(m_rgfAllowedTypes));
+ for (DWORD dw = 0; dw < dwAllowedTypeCount; dw += 1)
+ {
+ _ASSERTE(rgAllowedTypes[dw] != ObjectTypeIdCount);
+ m_rgfAllowedTypes[rgAllowedTypes[dw]] = TRUE;
+ }
+ };
+
+ CAllowedObjectTypes::CAllowedObjectTypes(
+ PalObjectTypeId eAllowedType
+ )
+ {
+ ZeroMemory(m_rgfAllowedTypes, sizeof(m_rgfAllowedTypes));
+
+ _ASSERTE(eAllowedType != ObjectTypeIdCount);
+ m_rgfAllowedTypes[eAllowedType] = TRUE;
+ };
+}
+
+#endif // _CORUNIX_H
+
diff --git a/src/pal/src/include/pal/critsect.h b/src/pal/src/include/pal/critsect.h
new file mode 100644
index 0000000000..50dea95bc5
--- /dev/null
+++ b/src/pal/src/include/pal/critsect.h
@@ -0,0 +1,45 @@
+// 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:
+
+ include/pal/critsect.h
+
+Abstract:
+
+ Header file for the critical sections functions.
+
+
+
+--*/
+
+#ifndef _PAL_CRITSECT_H_
+#define _PAL_CRITSECT_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+VOID InternalInitializeCriticalSection(CRITICAL_SECTION *pcs);
+VOID InternalDeleteCriticalSection(CRITICAL_SECTION *pcs);
+
+/* The following PALCEnterCriticalSection and PALCLeaveCriticalSection
+ functions are intended to provide CorUnix's InternalEnterCriticalSection
+ and InternalLeaveCriticalSection functionalities to legacy C code,
+ which has no knowledge of CPalThread, classes and namespaces.
+*/
+VOID PALCEnterCriticalSection(CRITICAL_SECTION *pcs);
+VOID PALCLeaveCriticalSection(CRITICAL_SECTION *pcs);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_CRITSECT_H_ */
+
diff --git a/src/pal/src/include/pal/cruntime.h b/src/pal/src/include/pal/cruntime.h
new file mode 100644
index 0000000000..65bf33c952
--- /dev/null
+++ b/src/pal/src/include/pal/cruntime.h
@@ -0,0 +1,247 @@
+// 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:
+
+ include/pal/cruntime.h
+
+Abstract:
+
+ Header file for C runtime utility functions.
+
+
+
+--*/
+
+#ifndef _PAL_CRUNTIME_H_
+#define _PAL_CRUNTIME_H_
+
+#include <string.h>
+#include <stdarg.h>
+#include <pthread.h>
+
+#ifdef __cplusplus
+typedef char16_t wchar_16; // __wchar_16 (which is defined in palinternal.h) is defined as wchar_16_cpp.
+
+extern "C"
+{
+#endif // __cplusplus
+
+typedef enum
+{
+ PFF_NONE = 0,
+ PFF_MINUS = 1,
+ PFF_POUND = 2,
+ PFF_ZERO = 4,
+ PFF_SPACE = 8,
+ PFF_PLUS = 16
+}PRINTF_FORMAT_FLAGS;
+
+typedef enum
+{
+ WIDTH_DEFAULT = -1,
+ WIDTH_STAR = -2, /* e.g. "%*.10s" */
+ WIDTH_INVALID = -3 /* e.g. "%*3.10s" */
+}WIDTH_FLAGS;
+
+typedef enum
+{
+ PRECISION_DEFAULT = -1,
+ PRECISION_STAR = -2, /* e.g. "%10.*s" */
+ PRECISION_DOT = -3, /* e.g. "%10.s" */
+ PRECISION_INVALID = -4 /* e.g. "%10.*3s" */
+}PRECISION_FLAGS;
+
+typedef enum
+{
+ PFF_PREFIX_DEFAULT = -1,
+ PFF_PREFIX_SHORT = 1,
+ PFF_PREFIX_LONG = 2,
+ PFF_PREFIX_LONGLONG = 3,
+ PFF_PREFIX_LONG_W = 4
+}PRINTF_PREFIXES;
+
+typedef enum
+{
+ PFF_TYPE_DEFAULT = -1,
+ PFF_TYPE_CHAR = 1,
+ PFF_TYPE_STRING = 2,
+ PFF_TYPE_WSTRING = 3,
+ PFF_TYPE_INT = 4,
+ PFF_TYPE_P = 5,
+ PFF_TYPE_N = 6,
+ PFF_TYPE_FLOAT = 7
+}PRINTF_TYPES;
+
+typedef enum
+{
+ SCANF_PREFIX_SHORT = 1,
+ SCANF_PREFIX_LONG = 2,
+ SCANF_PREFIX_LONGLONG = 3
+}SCANF_PREFIXES;
+
+typedef enum
+{
+ SCANF_TYPE_CHAR = 1,
+ SCANF_TYPE_STRING = 2,
+ SCANF_TYPE_INT = 3,
+ SCANF_TYPE_N = 4,
+ SCANF_TYPE_FLOAT = 5,
+ SCANF_TYPE_BRACKETS = 6,
+ SCANF_TYPE_SPACE = 7
+}SCANF_TYPES;
+
+/*******************************************************************************
+Function:
+ Internal_AddPaddingA
+
+Parameters:
+ Out
+ - buffer to place padding and given string (In)
+ Count
+ - maximum chars to be copied so as not to overrun given buffer
+ In
+ - string to place into (Out) accompanied with padding
+ Padding
+ - number of padding chars to add
+ Flags
+ - padding style flags (PRINTF_FORMAT_FLAGS)
+*******************************************************************************/
+BOOL Internal_AddPaddingA(LPSTR *Out, INT Count, LPSTR In, INT Padding, INT Flags);
+
+/*******************************************************************************
+Function:
+ PAL_printf_arg_remover
+
+Parameters:
+ ap
+ - pointer to the va_list from which to remove arguments
+ Width
+ - the width of the current format option
+ Precision
+ - the precision of the current format option
+ Type
+ - the type of the argument for the current format option
+ Prefix
+ - the prefix for the current format option
+*******************************************************************************/
+void PAL_printf_arg_remover(va_list *ap, INT Width, INT Precision, INT Type, INT Prefix);
+
+/*++
+Function:
+ Silent_PAL_vsnprintf
+
+See MSDN doc.
+--*/
+INT Silent_PAL_vsnprintf(LPSTR Buffer, INT Count, LPCSTR Format, va_list ap);
+
+/*++
+Function:
+ Silent_PAL_vfprintf
+
+See MSDN doc.
+--*/
+int Silent_PAL_vfprintf(PAL_FILE *stream, const char *format, va_list ap);
+
+
+
+/*++
+Function:
+ PAL_iswlower
+
+See MSDN
+
+--*/
+int __cdecl PAL_iswlower( wchar_16 c );
+
+
+/*++
+Function:
+ PAL_iswalpha
+
+See MSDN
+
+--*/
+int __cdecl PAL_iswalpha( wchar_16 c );
+
+#if HAVE_COREFOUNDATION
+/*--
+Function:
+ PAL_iswblank
+
+Returns TRUE if c is a Win32 "blank" character.
+--*/
+int __cdecl PAL_iswblank(wchar_16 c);
+
+/*--
+Function:
+ PAL_iswcntrl
+
+Returns TRUE if c is a control character.
+--*/
+int __cdecl PAL_iswcntrl(wchar_16 c);
+
+/*--
+Function:
+ PAL_iswcntrl
+
+Returns TRUE if c is a control character.
+--*/
+int __cdecl PAL_iswpunct(wchar_16 c);
+#endif // HAVE_COREFOUNDATION
+
+/*++
+
+struct PAL_FILE.
+Used to mimic the behavior of windows.
+fwrite under windows can set the ferror flag,
+under BSD fwrite doesn't.
+--*/
+struct _FILE
+{
+ FILE * bsdFilePtr; /* The BSD file to be passed to the
+ functions needing it. */
+
+ INT PALferrorCode; /* The ferror code that fwrite sets,
+ incase of error */
+
+ BOOL bTextMode; /* Boolean variable to denote that the
+ fle is opened in text/binary mode*/
+#if UNGETC_NOT_RETURN_EOF
+ BOOL bWriteOnlyMode;/* Boolean variable to denote that the
+ fle is opened in write-only mode*/
+#endif //UNGETC_NOT_RETURN_EOF
+};
+
+enum CRT_ERROR_CODES
+{
+ PAL_FILE_NOERROR = 0,
+ PAL_FILE_ERROR
+};
+
+/* Global variables storing the std streams. Defined in cruntime/file.c. */
+extern PAL_FILE PAL_Stdout;
+extern PAL_FILE PAL_Stdin;
+extern PAL_FILE PAL_Stderr;
+
+/*++
+
+Functio:
+
+ CRTInitStdStreams.
+
+ Initilizes the standard streams.
+ Returns TRUE on success, FALSE otherwise.
+--*/
+BOOL CRTInitStdStreams( void );
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_CRUNTIME_H_ */
diff --git a/src/pal/src/include/pal/cs.hpp b/src/pal/src/include/pal/cs.hpp
new file mode 100644
index 0000000000..76e268566b
--- /dev/null
+++ b/src/pal/src/include/pal/cs.hpp
@@ -0,0 +1,54 @@
+// 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.
+
+///////////////////////////////////////////////////////////////////////////////
+//
+// File:
+// cs.cpp
+//
+// Purpose:
+// Header file for critical sections implementation
+//
+
+//
+///////////////////////////////////////////////////////////////////////////////
+
+#ifndef _PAL_CS_HPP
+#define _PAL_CS_HPP
+
+#include "corunix.hpp"
+#include "critsect.h"
+
+namespace CorUnix
+{
+ void CriticalSectionSubSysInitialize(void);
+
+ void InternalInitializeCriticalSectionAndSpinCount(
+ PCRITICAL_SECTION pCriticalSection,
+ DWORD dwSpinCount,
+ bool fInternal);
+
+ void InternalEnterCriticalSection(
+ CPalThread *pThread,
+ CRITICAL_SECTION *pcs
+ );
+
+ void InternalLeaveCriticalSection(
+ CPalThread *pThread,
+ CRITICAL_SECTION *pcs
+ );
+
+ bool InternalTryEnterCriticalSection(
+ CPalThread * pThread,
+ PCRITICAL_SECTION pCriticalSection);
+
+#ifdef _DEBUG
+ void PALCS_ReportStatisticalData(void);
+ void PALCS_DumpCSList();
+#endif // _DEBUG
+
+}
+
+#endif // _PAL_CS_HPP
+
diff --git a/src/pal/src/include/pal/dbgmsg.h b/src/pal/src/include/pal/dbgmsg.h
new file mode 100644
index 0000000000..7a49fc0ad6
--- /dev/null
+++ b/src/pal/src/include/pal/dbgmsg.h
@@ -0,0 +1,628 @@
+// 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:
+
+ include/pal/dbgmsg.h
+
+Abstract:
+ Header file for Debug Message utilities. Output macros, type definitions,
+ extern variables. See overview section below for usage details.
+
+--*/
+
+/*
+Overview of Debug Message utilities
+
+Use debug channels to selectively output information to the console.
+
+Available macros :
+
+ - SET_DEFAULT_DEBUG_CHANNEL
+
+ This defines the channel to use with the macros TRACE, ERROR, etc
+ Use this macro once at the beginning of your source file.
+ (impl. details : this declares a constant static variable defdbgchan and
+ sets it to the apropriate channel)
+
+ usage : SET_DEFAULT_DEBUG_CHANNEL(somechannel);
+
+ - TRACE, ENTRY, WARN, ERROR, DBGOUT
+
+ Use this to output debug messages to the default debug channel (set with
+ SET_DEFAULT_DEBUG_CHANNEL). Messages will only be output if the channel is
+ active for the specified level.
+
+ usage : TRACE("printf format string", params...);
+
+ - TRACE_, ENTRY_, WARN_, ERROR_, DBGOUT_
+
+ Use this to autput debug messages to a channel other than the default.
+
+ usage : TRACE_(someotherchannel)("printf format string",params...);
+ ^ ^^ ^
+ don't forget the double set of parentheses!
+
+Available channels :
+ PAL : PAL-specific functionalities (PAL_Initialize, etc.)
+ LOADER : Loading API (LoadLibrary, etc); loader application
+ HANDLE : Handle manager (CloseHandle, etc.)
+ SHMEM : Shared Memory functions (for IPC)
+ PROCESS : Process related APIs
+ THREAD : Threading mechanism
+ EXCEPT : Structured Exception Handling functions
+ CRT : PAL implementation of the C Runtime Library functions
+ UNICODE : Unicode support API
+ ARCH : platform-dependent stuff
+ SYNC : Management of synchronization objects
+ FILE : File I/O API
+ VIRTUAL : Virtual memory and File mapping
+ MEM : Memory management (except Virtual* stuff)
+ SOCKET : WINSOCK implementation
+ DEBUG : Debugging API (ReadProcessMemory, etc.)
+ LOCALE : Locale support API
+ MISC : what doesn't fit anywhere else.
+ MUTEX : Mutex management functions
+ CRITSEC : Critical section API
+ POLL : ?
+ CRYPT : Cryptographic functions
+ SHFOLDER: Shared (well-known) folder functions
+ SXS : Side-by-side PALs (if supported)
+
+ Note : Most channels correspond to subdirectories $(PALROOT)
+ Note 2 : DON'T write TRACE("PAL") or TRACE(DCI_PAL), write TRACE(PAL)
+
+Available debug levels :
+ ENTRY : use this at the beginning of a function to print parameters.
+ TRACE : use this to output informational messages.
+ WARN : use this to report non-critical problems.
+ ERROR : use this to report critical problems.
+
+ DBGOUT: same as TRACE, but does not output line headers (thread ID, etc)
+
+Format specifiers :
+ These trace functions currently use the native fprintf() to output data.
+ All standard printf format specifiers should therefore work, while Microsoft
+ extensions will not.
+ There is one special case to consider : wide strings and wide characters.
+ Microsoft's extensions to printf include the specifiers %S and %C for
+ printing strings and characters of wchar_t. In the C99 standard,
+ the specifiers %ls and %ls serve the same purpose. However, Windows defines
+ wchar_t as a 16bit int, which is NOT guaranteed to match implementations
+ on other platforms. glibc on a x86 defines wchar_t as a 32bit int.
+ For this reason, %S and %C should be used in TRACE functions to output
+ Windows wide strings (of type wchar_t or WCHAR). To output wide-strings
+ in a platforms native format (litterals L"string" or variables of type
+ wchar_native), the specifiers %ls and %lc should be used instead.
+
+Using Debug channels at Run Time
+ To tell the PAL which debug channels should be open and which should be
+ closed, set the environment variable PAL_DBG_CHANNELS according to the
+ following syntax :
+ [+|-]<channel>.<level>[: ...]
+ + opens a channel, - closes it;
+ <channel> must be one of PAL, FILE, (etc), or the wildcard "all"
+ <level> must be TRACE, ENTRY, WARN, ERROR or "all"
+
+ Examples (for bash):
+
+ export PAL_DBG_CHANNELS="+PAL.TRACE:-FILE.ERROR"
+ export PAL_DBG_CHANNELS="+all.ENTRY"
+ export PAL_DBG_CHANNELS="-all.all"
+
+ To explicitly redirect the output of debug messages to a file (instead of
+ relying on the shell's > and |), set the environment variable
+ PAL_API_TRACING to the name of the file to write to. It can also be set to
+ "stdout" or "stderr". If PAL_API_TRACING is not set, output will go to
+ stderr.
+
+ ASSERT() messages cannot be controlled with PAL_DBG_CHANNELS; they can be
+ globally disabled (in debug builds) by setting the environment variable
+ PAL_DISABLE_ASSERTS to 1. In release builds, they will always be disabled
+
+ The environment variable "PAL_API_LEVELS" determines how many levels of
+ nesting will be allowed in ENTRY calls; if not set, the default is 1; a
+ value of 0 will allow infinite nesting, but will not indent the output
+
+ It is possible to disable/enable all channels during the execution of a
+ process; this involves using a debugger to modify a variable within the
+ address space of the running process. the variable is named
+ 'dbg_master_switch'; if set to zero, all debug chanels will be closed; if
+ set to nonzero, channels will be open or closed based on PAL_DBG_CHANNELS
+
+ Notes :
+ If _ENABLE_DEBUG_MESSAGES_ was not defined at build-time, no debug messages
+ will be generated.
+ If _ENABLE_DEBUG_MESSAGES_ was defined, all debug levels will be enabled,
+ but all channels will be closed by default
+
+ Another configure option is --enable-appendtraces
+ Normally, if the file specified by PAL_API_TRACING exists, its content will
+ be overwritten when a PAL process starts using it. If --enable-appendtraces
+ is used, debug output will be appended at the end of the file instead.
+
+
+
+ */
+
+#ifndef _PAL_DBGMSG_H_
+#define _PAL_DBGMSG_H_
+
+#include "pal/palinternal.h"
+#include "config.h"
+#include "pal/perftrace.h"
+#include "pal/debug.h"
+#include "pal/thread.hpp"
+#include "pal/tls.hpp"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/* Channel identifiers */
+typedef enum
+{
+ DCI_PAL,
+ DCI_LOADER,
+ DCI_HANDLE,
+ DCI_SHMEM,
+ DCI_PROCESS,
+ DCI_THREAD,
+ DCI_EXCEPT,
+ DCI_CRT,
+ DCI_UNICODE,
+ DCI_ARCH,
+ DCI_SYNC,
+ DCI_FILE,
+ DCI_VIRTUAL,
+ DCI_MEM,
+ DCI_SOCKET,
+ DCI_DEBUG,
+ DCI_LOCALE,
+ DCI_MISC,
+ DCI_MUTEX,
+ DCI_CRITSEC,
+ DCI_POLL,
+ DCI_CRYPT,
+ DCI_SHFOLDER,
+#ifdef FEATURE_PAL_SXS
+ DCI_SXS,
+#endif // FEATURE_PAL_SXS
+
+ DCI_LAST
+} DBG_CHANNEL_ID;
+
+/* Level identifiers */
+typedef enum
+{
+ DLI_ENTRY,
+ DLI_TRACE,
+ DLI_WARN,
+ DLI_ERROR,
+ DLI_ASSERT,
+ DLI_EXIT,
+
+ DLI_LAST
+} DBG_LEVEL_ID;
+
+
+/* extern variables */
+
+// Change W16_NULLSTRING to external variable to avoid multiple warnings showing up in prefast
+extern LPCWSTR W16_NULLSTRING;
+
+extern DWORD dbg_channel_flags[DCI_LAST];
+extern BOOL g_Dbg_asserts_enabled;
+
+/* we must use stdio functions directly rather that rely on PAL functions for
+ output, because those functions do tracing and we need to avoid recursion */
+extern FILE *output_file;
+
+/* master switch for debug channel enablement, to be modified by debugger */
+extern Volatile<BOOL> dbg_master_switch ;
+
+
+/* conditionnal compilation for other debug messages */
+#if !_ENABLE_DEBUG_MESSAGES_
+
+/* compile out these trace levels; see the definition of NOTRACE */
+#define TRACE NOTRACE
+#define TRACE_(x) NOTRACE
+#define WARN NOTRACE
+#define WARN_(x) NOTRACE
+#define ENTRY_EXTERNAL NOTRACE
+#define ENTRY NOTRACE
+#define ENTRY_(x) NOTRACE
+#define LOGEXIT NOTRACE
+#define LOGEXIT_(x) NOTRACE
+#define DBGOUT NOTRACE
+#define DBGOUT_(x) NOTRACE
+#define ERROR NOTRACE
+#define ERROR_(x) NOTRACE
+#define DBG_PRINTF(level, channel, bHeader) NOTRACE
+
+#define CHECK_STACK_ALIGN
+
+#define SET_DEFAULT_DEBUG_CHANNEL(x)
+#define DBG_ENABLED(level, channel)
+
+#else /* _ENABLE_DEBUG_MESSAGES_ */
+
+/* output macros */
+
+#define SET_DEFAULT_DEBUG_CHANNEL(x) \
+ static const DBG_CHANNEL_ID defdbgchan = DCI_##x
+
+/* Is debug output enabled for the given level and channel? */
+#define DBG_ENABLED(level, channel) (output_file && \
+ dbg_master_switch && \
+ (dbg_channel_flags[channel] & (1 << (level))))
+#define TRACE \
+ DBG_PRINTF(DLI_TRACE,defdbgchan,TRUE)
+
+#define TRACE_(x) \
+ DBG_PRINTF(DLI_TRACE,DCI_##x,TRUE)
+
+#define WARN \
+ DBG_PRINTF(DLI_WARN,defdbgchan,TRUE)
+
+#define WARN_(x) \
+ DBG_PRINTF(DLI_WARN,DCI_##x,TRUE)
+
+#if _DEBUG && defined(__APPLE__)
+bool DBG_ShouldCheckStackAlignment();
+#define CHECK_STACK_ALIGN if (DBG_ShouldCheckStackAlignment()) DBG_CheckStackAlignment()
+#else
+#define CHECK_STACK_ALIGN
+#endif
+
+#define ENTRY_EXTERNAL \
+ CHECK_STACK_ALIGN; \
+ DBG_PRINTF(DLI_ENTRY, defdbgchan,TRUE)
+
+#define ENTRY \
+ CHECK_STACK_ALIGN; \
+ DBG_PRINTF(DLI_ENTRY, defdbgchan,TRUE)
+
+#define ENTRY_(x) \
+ CHECK_STACK_ALIGN; \
+ DBG_PRINTF(DLI_ENTRY, DCI_##x,TRUE)
+
+#define LOGEXIT \
+ DBG_PRINTF(DLI_EXIT, defdbgchan,TRUE)
+
+#define LOGEXIT_(x) \
+ DBG_PRINTF(DLI_EXIT, DCI_##x,TRUE)
+
+#define DBGOUT \
+ DBG_PRINTF(DLI_TRACE,defdbgchan,FALSE)
+
+#define DBGOUT_(x) \
+ DBG_PRINTF(DLI_TRACE,DCI_##x,FALSE)
+
+/*Added this code here to stop error messages
+ *from appearing in retail build*/
+#define ERROR \
+ DBG_PRINTF(DLI_ERROR,defdbgchan,TRUE)
+
+#define ERROR_(x) \
+ DBG_PRINTF(DLI_ERROR,DCI_##x,TRUE)
+
+#define DBG_PRINTF(level, channel, bHeader) \
+{\
+ if( DBG_ENABLED(level, channel) ) { \
+ DBG_CHANNEL_ID __chanid=channel;\
+ DBG_LEVEL_ID __levid=level;\
+ BOOL __bHeader = bHeader;\
+ DBG_PRINTF2
+
+#ifdef __GNUC__
+#define DBG_PRINTF2(args...)\
+ DBG_printf_gcc(__chanid,__levid,__bHeader,__FUNCTION__,__FILE__,\
+ __LINE__,args);\
+ }\
+}
+#else /* __GNUC__ */
+#define DBG_PRINTF2(...)\
+ DBG_printf_c99(__chanid,__levid,__bHeader,__FILE__,__LINE__,__VA_ARGS__);\
+ }\
+}
+#endif /* __GNUC__ */
+
+#endif /* _ENABLE_DEBUG_MESSAGES_ */
+
+/* Use GNU C-specific features if available : __FUNCTION__ pseudo-macro,
+ variable-argument macros */
+#ifdef __GNUC__
+
+/* define NOTRACE as nothing; this will absorb the variable-argument list used
+ in tracing macros */
+#define NOTRACE(args...)
+
+#if defined(__cplusplus) && defined(FEATURE_PAL_SXS)
+#define __ASSERT_ENTER() \
+ /* DBG_printf_gcc() and DebugBreak() need a PAL thread */ \
+ PAL_EnterHolder __holder(PALIsThreadDataInitialized() && \
+ (CorUnix::InternalGetCurrentThread() == NULL || \
+ !CorUnix::InternalGetCurrentThread()->IsInPal()));
+#else /* __cplusplus && FEATURE_PAL_SXS */
+#define __ASSERT_ENTER()
+#endif /* __cplusplus && FEATURE_PAL_SXS */
+
+#if !defined(_DEBUG)
+
+#define ASSERT(args...)
+#define _ASSERT(expr)
+#define _ASSERTE(expr)
+#define _ASSERT_MSG(args...)
+
+#else /* defined(_DEBUG) */
+
+#define ASSERT(args...) \
+{ \
+ __ASSERT_ENTER(); \
+ if (output_file && dbg_master_switch) \
+ { \
+ DBG_printf_gcc(defdbgchan,DLI_ASSERT,TRUE,__FUNCTION__,__FILE__,__LINE__,args); \
+ } \
+ if (g_Dbg_asserts_enabled) \
+ { \
+ DebugBreak(); \
+ } \
+}
+
+#define _ASSERT(expr) do { if (!(expr)) { ASSERT(""); } } while(0)
+#define _ASSERTE(expr) do { if (!(expr)) { ASSERT("Expression: " #expr "\n"); } } while(0)
+#define _ASSERT_MSG(expr, args...) \
+ do { \
+ if (!(expr)) \
+ { \
+ ASSERT("Expression: " #expr ", Description: " args); \
+ } \
+ } while(0)
+
+#endif /* defined(_DEBUG) */
+
+#else /* __GNUC__ */
+/* Not GNU C : C99 [the latest version of the ISO C Standard] specifies
+ a different syntax for variable-argument macros, so try using that*/
+#if defined __STDC_VERSION__ && __STDC_VERSION__ >=199901L
+
+/* define NOTRACE as nothing; this will absorb the variable-argument list used
+ in tracing macros */
+#define NOTRACE(...)
+
+#if !defined(_DEBUG)
+
+#define ASSERT(...)
+#define _ASSERT(expr)
+#define _ASSERTE(expr)
+#define _ASSERT_MSG(...)
+
+#else /* defined(_DEBUG) */
+
+#define ASSERT(...) \
+{ \
+ __ASSERT_ENTER(); \
+ if (output_file && dbg_master_switch) \
+ { \
+ DBG_printf_c99(defdbgchan,DLI_ASSERT,TRUE,__FILE__,__LINE__,__VA_ARGS__); \
+ } \
+ if(g_Dbg_asserts_enabled) \
+ { \
+ PAL_Leave(); \
+ DebugBreak(); \
+ } \
+}
+
+#define _ASSERT(expr) do { if (!(expr)) { ASSERT(""); } } while(0)
+#define _ASSERTE(expr) do { if (!(expr)) { ASSERT("Expression: " #expr "\n"); } } while(0)
+#define _ASSERT_MSG(expr, ...) \
+ do { \
+ if (!(expr)) \
+ { \
+ ASSERT("Expression: " #expr ", Description: " __VA_ARGS__); \
+ } \
+ } while(0)
+
+#endif /* !_DEBUG */
+
+#else /* __STDC_VERSION__ */
+/* Not GNU C, not C99 :
+ possible work around for the lack of variable-argument macros:
+ by using 2 function calls; must wrap the whole thing in a critical
+ section to avoid interleaved output from multiple threads */
+
+#error The compiler is missing support for variable-argument macros.
+
+#endif /* __STDC_VERSION__*/
+#endif /* __GNUC__ */
+
+/* Function declarations */
+
+/*++
+Function :
+ DBG_init_channels
+
+ Initialize debug channel information based on environment settings
+ Call this only once at startup.
+
+ (no parameters, no return value)
+--*/
+BOOL DBG_init_channels(void);
+
+/*++
+Function :
+ DBG_close_channels
+
+ Close the output file for debug messages.
+
+ (no parameters, no return value)
+--*/
+void DBG_close_channels(void);
+
+/*++
+Function :
+ DBG_preprintf
+
+ Internal function for debug channels; don't use.
+ This function outputs the header information for debug messages (channel,
+ level, etc).
+
+Parameters :
+ DBG_CHANNEL_ID channel : debug channel to use
+ DBG_LEVEL_ID level : debug message level
+ BOOL bHeader : whether or not to output message header (thread id, etc)
+ LPSTR file : current file
+ INT line : line number
+
+Return Value :
+ TRUE if there's an output file, FALSE otherwise. this is so that
+ DBG_printf_plain doesn't get called unnecessarily.
+
+Notes :
+ This function is only used with compilers that don't support
+ variable-argument macros. It enters a critical section, which is left in
+ DBG_printf_plain.
+--*/
+BOOL DBG_preprintf(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
+ LPSTR file, INT line);
+
+/*++
+Function :
+ DBG_printf_gcc
+
+ Internal function for debug channels; don't use.
+ This function outputs a complete debug message, including the function name.
+
+Parameters :
+ DBG_CHANNEL_ID channel : debug channel to use
+ DBG_LEVEL_ID level : debug message level
+ BOOL bHeader : whether or not to output message header (thread id, etc)
+ LPSTR function : current function
+ LPSTR file : current file
+ INT line : line number
+ LPSTR format, ... : standard printf parameter list.
+
+Return Value :
+ always 1.
+
+Notes :
+ This version is for gnu compilers that support variable-argument macros
+ and the __FUNCTION__ pseudo-macro.
+
+--*/
+#if __GNUC__ && CHECK_TRACE_SPECIFIERS
+/* if requested, use an __attribute__ feature to ask gcc to check that format
+ specifiers match their parameters */
+int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
+ LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...)
+ __attribute__ ((format (printf,7, 8)));
+#else
+int DBG_printf_gcc(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
+ LPCSTR function, LPCSTR file, INT line, LPCSTR format, ...);
+#endif
+
+/*++
+Function :
+ DBG_printf_c99
+
+ Internal function for debug channels; don't use.
+ This function outputs a complete debug message, without function name.
+
+Parameters :
+ DBG_CHANNEL_ID channel : debug channel to use
+ DBG_LEVEL_ID level : debug message level
+ BOOL bHeader : whether or not to output message header (thread id, etc)
+ LPSTR file : current file
+ INT line : line number
+ LPSTR format, ... : standard printf parameter list.
+
+Return Value :
+ always 1.
+
+Notes :
+ This version is for compilers that support the C99 flavor of
+ variable-argument macros but not the gnu flavor, and do not support the
+ __FUNCTION__ pseudo-macro.
+
+--*/
+int DBG_printf_c99(DBG_CHANNEL_ID channel, DBG_LEVEL_ID level, BOOL bHeader,
+ LPSTR file, INT line, LPSTR format, ...);
+
+/*++
+Function :
+ DBG_printf_plain
+
+ Internal function for debug channels; don't use.
+ This function output the user-specified part of a debug-message.
+
+Parameters :
+ LPSTR format, ... : standard printf parameter list.
+
+Return value :
+ always 1.
+
+Notes :
+ This function is only used with compilers that don't support
+ variable-argument macros. It will leave the critical section entered in
+ DBG_preprintf.
+
+--*/
+int DBG_printf_plain(LPSTR format, ...);
+
+/*++
+Function :
+ DBG_change_entrylevel
+
+ retrieve current ENTRY nesting level and [optionnally] modify it
+
+Parameters :
+ int new_level : value to which the nesting level must be set, or -1
+
+Return value :
+ nesting level at the time the function was called
+
+Notes:
+if new_level is -1, the nesting level will not be modified
+--*/
+int DBG_change_entrylevel(int new_level);
+
+#ifdef __APPLE__
+/*++
+Function :
+ PAL_DisplayDialog
+
+ Display a simple modal dialog with an alert icon and a single OK button. Caller supplies the title of the
+ dialog and the main text. The dialog is displayed only if the COMPlus_EnableAssertDialog environment
+ variable is set to the value "1".
+
+--*/
+void PAL_DisplayDialog(const char *szTitle, const char *szText);
+
+/*++
+Function :
+ PAL_DisplayDialogFormatted
+
+ As above but takes a printf-style format string and insertion values to form the main text.
+
+--*/
+void PAL_DisplayDialogFormatted(const char *szTitle, const char *szTextFormat, ...);
+#else // __APPLE__
+#define PAL_DisplayDialog(_szTitle, _szText)
+#define PAL_DisplayDialogFormatted(_szTitle, _szTextFormat, args...)
+#endif // __APPLE__
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_DBGMSG_H_ */
+
+
diff --git a/src/pal/src/include/pal/debug.h b/src/pal/src/include/pal/debug.h
new file mode 100644
index 0000000000..78cdeff0c3
--- /dev/null
+++ b/src/pal/src/include/pal/debug.h
@@ -0,0 +1,86 @@
+// 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:
+
+ include/pal/debug.h
+
+Abstract:
+
+ Debug API utility functions
+
+
+
+--*/
+
+#ifndef _PAL_DEBUG_H_
+#define _PAL_DEBUG_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function :
+ DBG_DebugBreak
+
+ Processor-dependent implementation of DebugBreak
+
+(no parameters, no return value)
+--*/
+extern "C" VOID
+DBG_DebugBreak();
+
+/*++
+Function:
+ IsInDebugBreak(addr)
+
+ Returns true if the address is in DBG_DebugBreak.
+
+--*/
+BOOL
+IsInDebugBreak(void *addr);
+
+/*++
+Function :
+ DBG_FlushInstructionCache
+
+ Processor-dependent implementation of FlushInstructionCache
+
+Parameters :
+ LPCVOID lpBaseAddress: start of region to flush
+ SIZE_T dwSize : length of region to flush
+
+Return value :
+ TRUE on success, FALSE on failure
+
+--*/
+BOOL
+DBG_FlushInstructionCache(
+ IN LPCVOID lpBaseAddress,
+ IN SIZE_T dwSize);
+
+#if defined(__APPLE__)
+/*++
+Function:
+ DBG_CheckStackAlignment
+
+ The Apple ABI requires 16-byte alignment on the stack pointer.
+ This function traps/interrupts otherwise.
+--*/
+VOID
+DBG_CheckStackAlignment();
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //PAL_DEBUG_H_
diff --git a/src/pal/src/include/pal/dtraceprotocol.h b/src/pal/src/include/pal/dtraceprotocol.h
new file mode 100644
index 0000000000..d1a17a71ae
--- /dev/null
+++ b/src/pal/src/include/pal/dtraceprotocol.h
@@ -0,0 +1,39 @@
+// 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.
+//
+// File: rotor/pal/corunix/include/pal/dtrace_protocal.h
+//
+
+//
+// Header file for the protocals between CLR and Dtrace server
+//
+// ======================================================================================
+
+#ifndef DTRACE_PROTOCOL_H
+#define DTRACE_PROTOCOL_H
+
+// Start DTrace Consumer by Unix Domain App
+#define kServerSocketPath "/Library/Application Support/com.microsoft.clr.CFDtraceServer/Socket"
+#define kPacketTypeStartDtrace 1
+#define kPacketTypeReply 3
+#define kMaxMessageSize 318
+#define kPacketMaximumSize 102400
+
+struct PacketHeader {
+ int fType; // for request from client to server, it should be kPacketTypeStartDtrace
+ // for reply from server to client, it should be kPacketTypeReply
+ unsigned int fSize; // includes size of header itself
+};
+
+struct PacketStartDTrace { // reply: PacketReply
+ PacketHeader fHeader; // fType is kPacketTypeStartDtrace
+ char fMessage[kMaxMessageSize]; // message to print
+};
+
+struct PacketReply { // reply: n/a
+ PacketHeader fHeader; // fType is kPacketTypeReply
+ int fErr; // result of operation, errno-style
+};
+
+#endif // DTRACE_PROTOCOL
diff --git a/src/pal/src/include/pal/environ.h b/src/pal/src/include/pal/environ.h
new file mode 100644
index 0000000000..1c0bce21ca
--- /dev/null
+++ b/src/pal/src/include/pal/environ.h
@@ -0,0 +1,78 @@
+// 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:
+
+ include/pal/environ.h
+
+Abstract:
+ Header file for functions manipulating environment variables
+
+
+--*/
+
+#ifndef __ENVIRON_H_
+#define __ENVIRON_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Variables :
+
+ palEnvironment: a global variable equivalent to environ on systems on
+ which that exists, and a pointer to an array of environment
+ strings on systems without environ.
+ gcsEnvironment: critical section to synchronize access to palEnvironment
+--*/
+extern char **palEnvironment;
+extern CRITICAL_SECTION gcsEnvironment;
+
+/*++
+
+Function:
+ EnvironInitialize
+
+Initialization function for the PAL environment code.
+--*/
+BOOL EnvironInitialize();
+
+/*++
+Function:
+ EnvironGetenv
+
+Get the value of environment variable with the given name.
+--*/
+char *EnvironGetenv(const char *name, BOOL copyValue = TRUE);
+
+/*++
+Function:
+ EnvironPutenv
+
+Add the environment variable string provided to the PAL version
+of the environment.
+--*/
+BOOL EnvironPutenv(const char *string, BOOL deleteIfEmpty);
+
+/*++
+Function:
+ EnvironUnsetenv
+
+Remove the environment variable with the given name from the PAL
+version of the environment if it exists.
+--*/
+void EnvironUnsetenv(const char *name);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* __ENVIRON_H_ */
+
diff --git a/src/pal/src/include/pal/event.hpp b/src/pal/src/include/pal/event.hpp
new file mode 100644
index 0000000000..98eeaee5db
--- /dev/null
+++ b/src/pal/src/include/pal/event.hpp
@@ -0,0 +1,69 @@
+// 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:
+
+ event.hpp
+
+Abstract:
+
+ Event object structure definition.
+
+
+
+--*/
+
+#ifndef _PAL_EVENT_H_
+#define _PAL_EVENT_H_
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+ extern CObjectType otManualResetEvent;
+ extern CObjectType otAutoResetEvent;
+
+ PAL_ERROR
+ InternalCreateEvent(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpEventAttributes,
+ BOOL bManualReset,
+ BOOL bInitialState,
+ LPCWSTR lpName,
+ HANDLE *phEvent
+ );
+
+ PAL_ERROR
+ InternalSetEvent(
+ CPalThread *pThread,
+ HANDLE hEvent,
+ BOOL fSetEvent
+ );
+
+ PAL_ERROR
+ InternalOpenEvent(
+ CPalThread *pThread,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName,
+ HANDLE *phEvent
+ );
+
+}
+
+#endif //PAL_EVENT_H_
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/src/include/pal/fakepoll.h b/src/pal/src/include/pal/fakepoll.h
new file mode 100644
index 0000000000..eec40d6612
--- /dev/null
+++ b/src/pal/src/include/pal/fakepoll.h
@@ -0,0 +1,68 @@
+// 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.
+
+// fakepoll.h
+// poll using select
+// Warning: a call to this poll() takes about 4K of stack space.
+
+// Greg Parker gparker@cs.stanford.edu December 2000
+// This code is in the public domain and may be copied or modified without
+// permission.
+
+// Located at <http://www.sealiesoftware.com/fakepoll.h>.
+
+
+
+
+#ifndef _FAKE_POLL_H
+#define _FAKE_POLL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#ifdef FD_SETSIZE
+#undef FD_SETSIZE
+#endif
+#define FD_SETSIZE OPEN_MAX
+
+typedef struct pollfd {
+ int fd; /* file desc to poll */
+ short events; /* events of interest on fd */
+ short revents; /* events that occurred on fd */
+} pollfd_t;
+
+// Typically defined in sys/stropts.h and used for an infinite timeout.
+#ifndef _INFTIM
+#define _INFTIM -1
+#endif
+#ifndef INFTIM
+#define INFTIM _INFTIM
+#endif
+
+// poll flags
+#define POLLIN 0x0001
+#define POLLOUT 0x0004
+#define POLLERR 0x0008
+
+// synonyms
+#define POLLNORM POLLIN
+#define POLLPRI POLLIN
+#define POLLRDNORM POLLIN
+#define POLLRDBAND POLLIN
+#define POLLWRNORM POLLOUT
+#define POLLWRBAND POLLOUT
+
+// ignored
+#define POLLHUP 0x0010
+#define POLLNVAL 0x0020
+
+int poll(struct pollfd *pollSet, int pollCount, int pollTimeout);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _FAKE_POLL_H */
diff --git a/src/pal/src/include/pal/file.h b/src/pal/src/include/pal/file.h
new file mode 100644
index 0000000000..93c8ad9784
--- /dev/null
+++ b/src/pal/src/include/pal/file.h
@@ -0,0 +1,304 @@
+// 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:
+
+ include/pal/file.h
+
+Abstract:
+ Header file for file utility functions.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_FILE_H_
+#define _PAL_FILE_H_
+
+#include "pal/shmemory.h"
+#include "pal/stackstring.hpp"
+#include <sys/types.h>
+#include <dirent.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+typedef struct _find_handle
+{
+ struct _find_handle *self_addr; /* for pointer verification */
+
+ char dir[_MAX_DIR];
+ char fname[MAX_PATH_FNAME]; /* includes extension */
+ glob_t gGlob;
+ char **next;
+} find_obj;
+
+/*++
+FILECanonicalizePath
+ Removes all instances of '/./', '/../' and '//' from an absolute path.
+
+Parameters:
+ LPSTR lpUnixPath : absolute path to modify, in Unix format
+
+(no return value)
+
+Notes :
+-behavior is undefined if path is not absolute
+-the order of steps *is* important: /one/./../two would give /one/two
+ instead of /two if step 3 was done before step 2
+-reason for this function is that GetFullPathName can't use realpath(), since
+ realpath() requires the given path to be valid and GetFullPathName does not.
+--*/
+void FILECanonicalizePath(LPSTR lpUnixPath);
+
+/*++
+Function:
+ FileDosToUnixPathA
+
+Abstract:
+ Change a DOS path to a Unix path. Replace '\' by '/'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+--*/
+void
+FILEDosToUnixPathA(LPSTR lpPath);
+
+/*++
+Function:
+ FileDosToUnixPathW
+
+Abstract:
+ Change a DOS path to a Unix path. Replace '\' by '/'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+ --*/
+void
+FILEDosToUnixPathW(LPWSTR lpPath);
+
+/*++
+Function:
+ FileUnixToDosPathA
+
+Abstract:
+ Change a Unix path to a DOS path. Replace '/' by '\'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+--*/
+void
+FILEUnixToDosPathA(LPSTR lpPath);
+
+/*++
+Function:
+ FILEGetDirectoryFromFullPathA
+
+Parse the given path. If it contains a directory part and a file part,
+put the directory part into the supplied buffer, and return the number of
+characters written to the buffer. If the buffer is not large enough,
+return the required size of the buffer including the NULL character. If
+there is no directory part in the path, return 0.
+--*/
+DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath,
+ DWORD nBufferLength,
+ LPSTR lpBuffer );
+
+/*++
+Function:
+ FILEGetFileNameFromFullPath
+
+Given a full path, return a pointer to the first char of the filename part.
+--*/
+LPCSTR FILEGetFileNameFromFullPathA( LPCSTR lpFullPath );
+
+/*++
+Function:
+ FILEGetLastErrorFromErrno
+
+Convert errno into the appropriate win32 error and return it.
+--*/
+DWORD FILEGetLastErrorFromErrno( void );
+
+/*++
+Function:
+ DIRGetLastErrorFromErrno
+
+Convert errno into the appropriate win32 error and return it.
+--*/
+DWORD DIRGetLastErrorFromErrno( void );
+
+/*++
+FILEInitStdHandles
+
+Create handle objects for stdin, stdout and stderr
+
+(no parameters)
+
+Return value:
+ TRUE on success, FALSE on failure
+--*/
+BOOL FILEInitStdHandles(void);
+
+/*++
+FILECleanupStdHandles
+
+Close promary handles for stdin, stdout and stderr
+
+(no parameters, no return value)
+--*/
+void FILECleanupStdHandles(void);
+
+/*++
+
+Function :
+ FILEGetProperNotFoundError
+
+Returns the proper error code, based on the
+Windows behavoir.
+
+ IN LPSTR lpPath - The path to check.
+ LPDWORD lpErrorCode - The error to set.
+*/
+void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode );
+
+/*++
+PAL__getcwd
+
+Calls getcwd
+
+Input parameters:
+
+char *szBuf = a copy of the absolute pathname of the current working directory
+is copied into szBuf.
+size_t nSize = size, in bytes, of the array referenced by szBuf.
+
+Return value:
+ A pointer to the pathname if successful, otherwise NULL is returned.
+--*/
+char * __cdecl PAL__getcwd(char *szBuf, size_t nSize);
+
+/*++
+PAL_fflush
+
+Calls fflush
+
+Input parameters:
+
+PAL_FILE *stream = stream to be flushed.
+
+Return value:
+ 0 is returned on success, otherwise EOF is returned.
+--*/
+int _cdecl PAL_fflush( PAL_FILE *stream );
+
+/*++
+PAL_mkstemp
+
+Calls InternalMkstemp to call mkstemp
+
+Input parameters:
+
+char *szNameTemplate = the pattern to follow when creating a new file.
+
+Return value:
+ file descriptor of opened file on success, -1 on failure.
+--*/
+int __cdecl PAL_mkstemp(char *szNameTemplate);
+
+/*++
+PAL_rename
+
+Calls rename
+
+Input parameters:
+
+szOldName = pointer to the pathname of the file to be renamed
+szNewName = pointer to the new pathname of the file
+
+Return value:
+ Returns 0 on success and -1 on failure
+--*/
+int __cdecl PAL_rename(const char *szOldName, const char *szNewName);
+
+/*++
+PAL_fgets
+
+Wrapper function for InternalFgets.
+
+Input parameters:
+
+sz = stores characters read from the given file stream
+nSize = number of characters to be read
+pf = stream to read characters from
+
+Return value:
+ Returns a pointer to the string storing the characters on success
+ and NULL on failure.
+--*/
+char * __cdecl PAL_fgets(char *sz, int nSize, PAL_FILE *pf);
+
+/*++
+PAL_fwrite
+
+Wrapper function for InternalFwrite
+
+Input parameters:
+
+pvBuffer = array of objects to write to the given file stream
+nSize = size of a object in bytes
+nCount = number of objects to write
+pf = stream to write characters to
+
+Return value:
+ Returns the number of objects written.
+--*/
+size_t __cdecl PAL_fwrite(const void *pvBuffer, size_t nSize, size_t nCount, PAL_FILE *pf);
+
+/*++
+PAL__open
+
+Wrapper function for InternalOpen.
+
+Input parameters:
+
+szPath = pointer to a pathname of a file to be opened
+nFlags = arguments that control how the file should be accessed
+mode = file permission settings that are used only when a file is created
+
+Return value:
+ File descriptor on success, -1 on failure
+--*/
+int __cdecl PAL__open(const char *szPath, int nFlags, ...);
+
+/*++
+PAL_fseek
+
+Wrapper function for fseek
+
+Input parameters:
+
+pf = a given file stream
+lOffset = distance from position to set file-position indicator
+nWhence = method used to determine the file_position indicator location relative to lOffset
+
+Return value:
+ 0 on success, -1 on failure.
+--*/
+int _cdecl PAL_fseek(PAL_FILE *pf, LONG lOffset, int nWhence);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_FILE_H_ */
+
diff --git a/src/pal/src/include/pal/file.hpp b/src/pal/src/include/pal/file.hpp
new file mode 100644
index 0000000000..5acccb0a24
--- /dev/null
+++ b/src/pal/src/include/pal/file.hpp
@@ -0,0 +1,365 @@
+// 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:
+
+ include/pal/file.hpp
+
+Abstract:
+ Header file for file utility functions.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_FILE_HPP_
+#define _PAL_FILE_HPP_
+
+#include "corunix.hpp"
+#include "pal/stackstring.hpp"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <dirent.h>
+
+
+namespace CorUnix
+{
+ extern CObjectType otFile;
+ extern CAllowedObjectTypes aotFile;
+
+ class CFileProcessLocalData
+ {
+ public:
+ IFileLockController *pLockController;
+
+ int unix_fd;
+ DWORD dwDesiredAccess; /* Unix assumes files are always opened for reading.
+ In Windows we can open a file for writing only */
+ int open_flags; /* stores Unix file creation flags */
+ BOOL open_flags_deviceaccessonly;
+ char unix_filename[MAXPATHLEN];
+ BOOL inheritable;
+ };
+
+ PAL_ERROR
+ InternalCreateFile(
+ CPalThread *pThread,
+ LPCSTR lpFileName,
+ DWORD dwDesiredAccess,
+ DWORD dwShareMode,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ DWORD dwCreationDisposition,
+ DWORD dwFlagsAndAttributes,
+ HANDLE hTemplateFile,
+ HANDLE *pFileHandle
+ );
+
+ PAL_ERROR
+ InternalWriteFile(
+ CPalThread *pThread,
+ HANDLE hFile,
+ LPCVOID lpBuffer,
+ DWORD nNumberOfBytesToWrite,
+ LPDWORD lpNumberOfBytesWritten,
+ LPOVERLAPPED lpOverlapped
+ );
+
+ PAL_ERROR
+ InternalReadFile(
+ CPalThread *pThread,
+ HANDLE hFile,
+ LPVOID lpBuffer,
+ DWORD nNumberOfBytesToRead,
+ LPDWORD lpNumberOfBytesRead,
+ LPOVERLAPPED lpOverlapped
+ );
+
+ PAL_ERROR
+ InternalSetEndOfFile(
+ CPalThread *pThread,
+ HANDLE hFile
+ );
+
+ PAL_ERROR
+ InternalGetFileSize(
+ CPalThread *pThread,
+ HANDLE hFile,
+ DWORD *pdwFileSizeLow,
+ DWORD *pdwFileSizeHigh
+ );
+
+ PAL_ERROR
+ InternalFlushFileBuffers(
+ CPalThread *pThread,
+ HANDLE hFile
+ );
+
+ PAL_ERROR
+ InternalGetFileType(
+ CPalThread *pThread,
+ HANDLE hFile,
+ DWORD *pdwFileType
+ );
+
+ PAL_ERROR
+ InternalCreatePipe(
+ CPalThread *pThread,
+ HANDLE *phReadPipe,
+ HANDLE *phWritePipe,
+ LPSECURITY_ATTRIBUTES lpPipeAttributes,
+ DWORD nSize
+ );
+
+ PAL_ERROR
+ InternalLockFile(
+ CPalThread *pThread,
+ HANDLE hFile,
+ DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToLockLow,
+ DWORD nNumberOfBytesToLockHigh
+ );
+
+ PAL_ERROR
+ InternalUnlockFile(
+ CPalThread *pThread,
+ HANDLE hFile,
+ DWORD dwFileOffsetLow,
+ DWORD dwFileOffsetHigh,
+ DWORD nNumberOfBytesToUnlockLow,
+ DWORD nNumberOfBytesToUnlockHigh
+ );
+
+ PAL_ERROR
+ InternalSetFilePointer(
+ CPalThread *pThread,
+ HANDLE hFile,
+ LONG lDistanceToMove,
+ PLONG lpDistanceToMoveHigh,
+ DWORD dwMoveMethod,
+ PLONG lpNewFilePointerLow
+ );
+
+ PAL_ERROR
+ InternalSetFileTime(
+ CPalThread *pThread,
+ IN HANDLE hFile,
+ IN CONST FILETIME *lpCreationTime,
+ IN CONST FILETIME *lpLastAccessTime,
+ IN CONST FILETIME *lpLastWriteTime
+ );
+
+ PAL_ERROR
+ InternalGetFileTime(
+ CPalThread *pThread,
+ IN HANDLE hFile,
+ OUT LPFILETIME lpCreationTime,
+ OUT LPFILETIME lpLastAccessTime,
+ OUT LPFILETIME lpLastWriteTime
+ );
+
+ BOOL
+ RealPathHelper(LPCSTR lpUnixPath, PathCharString& lpBuffer);
+ /*++
+ InternalCanonicalizeRealPath
+ Wraps realpath() to hide platform differences. See the man page for
+ realpath(3) for details of how realpath() works.
+
+ On systems on which realpath() allows the last path component to not
+ exist, this is a straight thunk through to realpath(). On other
+ systems, we remove the last path component, then call realpath().
+ --*/
+ PAL_ERROR
+ InternalCanonicalizeRealPath(
+ LPCSTR lpUnixPath,
+ PathCharString& lpBuffer
+ );
+
+ /*++
+ InternalMkstemp
+ Wraps mkstemp
+ --*/
+ int
+ InternalMkstemp(
+ char *szNameTemplate
+ );
+
+ /*++
+ InternalFgets
+ Wraps fgets
+ --*/
+ char *
+ InternalFgets(
+ char *sz,
+ int nSize,
+ FILE *f,
+ bool fTextMode
+ );
+
+ /*++
+ InternalFwrite
+ Wraps fwrite
+ --*/
+ size_t
+ InternalFwrite(
+ const void *pvBuffer,
+ size_t nSize,
+ size_t nCount,
+ FILE *f,
+ INT *pnErrorCode
+ );
+
+ /*++
+ InternalOpen
+ Wraps open
+ --*/
+ int
+ InternalOpen(
+ const char *szFilename,
+ int nFlags,
+ ...
+ );
+}
+
+extern "C"
+{
+
+//
+// These routines should all be separated out into something along the lines
+// of fileutils.* (instead of being commingled with the core file object
+// code).
+//
+
+/*++
+FILECanonicalizePath
+ Removes all instances of '/./', '/../' and '//' from an absolute path.
+
+Parameters:
+ LPSTR lpUnixPath : absolute path to modify, in Unix format
+
+(no return value)
+
+Notes :
+-behavior is undefined if path is not absolute
+-the order of steps *is* important: /one/./../two would give /one/two
+ instead of /two if step 3 was done before step 2
+-reason for this function is that GetFullPathName can't use realpath(), since
+ realpath() requires the given path to be valid and GetFullPathName does not.
+--*/
+void FILECanonicalizePath(LPSTR lpUnixPath);
+
+/*++
+Function:
+ FileDosToUnixPathA
+
+Abstract:
+ Change a DOS path to a Unix path. Replace '\' by '/'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+--*/
+void
+FILEDosToUnixPathA(LPSTR lpPath);
+
+/*++
+Function:
+ FileDosToUnixPathW
+
+Abstract:
+ Change a DOS path to a Unix path. Replace '\' by '/'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+ --*/
+void
+FILEDosToUnixPathW(LPWSTR lpPath);
+
+/*++
+Function:
+ FileUnixToDosPathA
+
+Abstract:
+ Change a Unix path to a DOS path. Replace '/' by '\'.
+
+Parameter:
+ IN/OUT lpPath: path to be modified
+--*/
+void
+FILEUnixToDosPathA(LPSTR lpPath);
+
+
+/*++
+Function:
+ FILEGetDirectoryFromFullPathA
+
+Parse the given path. If it contains a directory part and a file part,
+put the directory part into the supplied buffer, and return the number of
+characters written to the buffer. If the buffer is not large enough,
+return the required size of the buffer including the NULL character. If
+there is no directory part in the path, return 0.
+--*/
+DWORD FILEGetDirectoryFromFullPathA( LPCSTR lpFullPath,
+ DWORD nBufferLength,
+ LPSTR lpBuffer );
+
+/*++
+Function:
+ FILEGetFileNameFromFullPath
+
+Given a full path, return a pointer to the first char of the filename part.
+--*/
+LPCSTR FILEGetFileNameFromFullPathA( LPCSTR lpFullPath );
+
+/*++
+Function:
+ FILEGetLastErrorFromErrno
+
+Convert errno into the appropriate win32 error and return it.
+--*/
+DWORD FILEGetLastErrorFromErrno( void );
+
+/*++
+FILEInitStdHandles
+
+Create handle objects for stdin, stdout and stderr
+
+(no parameters)
+
+Return value:
+ TRUE on success, FALSE on failure
+--*/
+BOOL FILEInitStdHandles(void);
+
+/*++
+FILECleanupStdHandles
+
+Close primary handles for stdin, stdout and stderr
+
+(no parameters, no return value)
+--*/
+void FILECleanupStdHandles(void);
+
+/*++
+
+Function :
+ FILEGetProperNotFoundError
+
+Returns the proper error code, based on the
+Windows behavoir.
+
+ IN LPSTR lpPath - The path to check.
+ LPDWORD lpErrorCode - The error to set.
+*/
+void FILEGetProperNotFoundError( LPCSTR lpPath, LPDWORD lpErrorCode );
+
+}
+
+#endif /* _PAL_FILE_HPP_ */
+
diff --git a/src/pal/src/include/pal/filetime.h b/src/pal/src/include/pal/filetime.h
new file mode 100644
index 0000000000..cb37b4115a
--- /dev/null
+++ b/src/pal/src/include/pal/filetime.h
@@ -0,0 +1,80 @@
+// 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:
+
+ include/pal/filetime.h
+
+Abstract:
+
+ Header file for utility functions having to do with file times.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_FILETIME_H_
+#define _PAL_FILETIME_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/* Provide consistent access to nanosecond fields, if they exist. */
+
+#if HAVE_STAT_TIMESPEC
+
+#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atimespec.tv_nsec)
+#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtimespec.tv_nsec)
+#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctimespec.tv_nsec)
+
+#else /* HAVE_STAT_TIMESPEC */
+
+#if HAVE_STAT_NSEC
+
+#define ST_ATIME_NSEC(statstruct) ((statstruct)->st_atimensec)
+#define ST_MTIME_NSEC(statstruct) ((statstruct)->st_mtimensec)
+#define ST_CTIME_NSEC(statstruct) ((statstruct)->st_ctimensec)
+
+#else /* HAVE_STAT_NSEC */
+
+#define ST_ATIME_NSEC(statstruct) 0
+#define ST_MTIME_NSEC(statstruct) 0
+#define ST_CTIME_NSEC(statstruct) 0
+
+#endif /* HAVE_STAT_NSEC */
+#endif /* HAVE_STAT_TIMESPEC */
+
+FILETIME FILEUnixTimeToFileTime( time_t sec, long nsec );
+time_t FILEFileTimeToUnixTime( FILETIME FileTime, long *nsec );
+
+#ifdef __APPLE__
+#include <CoreFoundation/CFDate.h>
+
+FILETIME FILECFAbsoluteTimeToFileTime( CFAbsoluteTime sec );
+#endif // __APPLE__
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_FILE_H_ */
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/src/include/pal/handleapi.hpp b/src/pal/src/include/pal/handleapi.hpp
new file mode 100644
index 0000000000..7974432a65
--- /dev/null
+++ b/src/pal/src/include/pal/handleapi.hpp
@@ -0,0 +1,48 @@
+// 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:
+
+ handleapi.hpp
+
+Abstract:
+
+ Declaration of the handle management APIs
+
+
+
+--*/
+
+#ifndef _HANDLEAPI_HPP
+#define _HANDLEAPI_HPP
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+ PAL_ERROR
+ InternalDuplicateHandle(
+ CPalThread *pThread,
+ HANDLE hSourceProcess,
+ HANDLE hSource,
+ HANDLE hTargetProcess,
+ LPHANDLE phDuplicate,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ DWORD dwOptions
+ );
+
+ PAL_ERROR
+ InternalCloseHandle(
+ CPalThread *pThread,
+ HANDLE hObject
+ );
+}
+
+#endif // _HANDLEAPI_HPP
+
diff --git a/src/pal/src/include/pal/handlemgr.hpp b/src/pal/src/include/pal/handlemgr.hpp
new file mode 100644
index 0000000000..1fbdb87199
--- /dev/null
+++ b/src/pal/src/include/pal/handlemgr.hpp
@@ -0,0 +1,180 @@
+// 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:
+
+ handlemgr.hpp
+
+Abstract:
+
+ Simple handle table manager class
+
+
+
+--*/
+
+#ifndef _PAL_HANDLEMGR_H_
+#define _PAL_HANDLEMGR_H_
+
+
+#include "corunix.hpp"
+#include "cs.hpp"
+#include "pal/thread.hpp"
+#include "pal/malloc.hpp"
+
+
+/* Pseudo handles constant for current thread and process */
+extern const HANDLE hPseudoCurrentProcess;
+extern const HANDLE hPseudoCurrentThread;
+extern const HANDLE hPseudoGlobalIOCP;
+
+namespace CorUnix
+{
+ class CSimpleHandleManager
+ {
+ private:
+ enum { c_BasicGrowthRate = 1024 };
+ enum { c_MaxIndex = 0x3FFFFFFE };
+
+ typedef UINT_PTR HANDLE_INDEX;
+ static const HANDLE_INDEX c_hiInvalid = (HANDLE_INDEX) -1;
+
+ HANDLE
+ HandleIndexToHandle(HANDLE_INDEX hi)
+ {
+ return (HANDLE) ((hi + 1) << 2);
+ };
+
+ HANDLE_INDEX
+ HandleToHandleIndex(HANDLE h)
+ {
+ return (HANDLE_INDEX) (((UINT_PTR) h) >> 2) - 1;
+ };
+
+ typedef struct _HANDLE_TABLE_ENTRY
+ {
+ union
+ {
+ IPalObject *pObject;
+ HANDLE_INDEX hiNextIndex;
+ } u;
+
+ DWORD dwAccessRights;
+ bool fInheritable;
+
+ bool fEntryAllocated;
+ } HANDLE_TABLE_ENTRY;
+
+ HANDLE_INDEX m_hiFreeListStart;
+ HANDLE_INDEX m_hiFreeListEnd;
+
+ DWORD m_dwTableSize;
+ DWORD m_dwTableGrowthRate;
+ HANDLE_TABLE_ENTRY* m_rghteHandleTable;
+
+ CRITICAL_SECTION m_csLock;
+ bool m_fLockInitialized;
+
+ bool ValidateHandle(HANDLE h);
+
+ public:
+
+ CSimpleHandleManager()
+ :
+ m_hiFreeListStart(c_hiInvalid),
+ m_hiFreeListEnd(c_hiInvalid),
+ m_dwTableSize(0),
+ m_dwTableGrowthRate(c_BasicGrowthRate),
+ m_rghteHandleTable(NULL),
+ m_fLockInitialized(FALSE)
+ {
+ };
+
+ virtual
+ ~CSimpleHandleManager()
+ {
+ if (m_fLockInitialized)
+ {
+ DeleteCriticalSection(&m_csLock);
+ }
+
+ if (NULL != m_rghteHandleTable)
+ {
+ free(m_rghteHandleTable);
+ }
+ }
+
+ PAL_ERROR
+ Initialize(
+ void
+ );
+
+ PAL_ERROR
+ AllocateHandle(
+ CPalThread *pThread,
+ IPalObject *pObject,
+ DWORD dwAccessRights,
+ bool fInheritable,
+ HANDLE *ph
+ );
+
+ //
+ // On success this will add a reference to the returned object.
+ //
+
+ PAL_ERROR
+ GetObjectFromHandle(
+ CPalThread *pThread,
+ HANDLE h,
+ DWORD *pdwRightsGranted,
+ IPalObject **ppObject
+ );
+
+ PAL_ERROR
+ FreeHandle(
+ CPalThread *pThread,
+ HANDLE h
+ );
+
+ void
+ Lock(
+ CPalThread *pThread
+ )
+ {
+ InternalEnterCriticalSection(pThread, &m_csLock);
+ };
+
+ void
+ Unlock(
+ CPalThread *pThread
+ )
+ {
+ InternalLeaveCriticalSection(pThread, &m_csLock);
+ };
+ };
+
+ bool
+ HandleIsSpecial(
+ HANDLE h
+ );
+}
+
+#endif // _PAL_HANDLEMGR_H_
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/src/include/pal/identity.hpp b/src/pal/src/include/pal/identity.hpp
new file mode 100644
index 0000000000..bd64a659ac
--- /dev/null
+++ b/src/pal/src/include/pal/identity.hpp
@@ -0,0 +1,57 @@
+// 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:
+
+ include/pal/identity.hpp
+
+Abstract:
+
+ Header file for identity functions.
+
+
+
+--*/
+
+#ifndef _PAL_IDENTITY_HPP_
+#define _PAL_IDENTITY_HPP_
+
+#include "config.h"
+#include "pal/palinternal.h"
+
+/*++
+
+Function:
+ IdentityInitialize
+
+--*/
+BOOL IdentityInitialize();
+
+/*++
+Function:
+ IdentityCleanup
+
+--*/
+VOID IdentityCleanup();
+
+#if HAVE_GETPWUID_R
+namespace CorUnix
+{
+ int
+ InternalGetpwuid_r(
+ CPalThread *pPalThread,
+ uid_t uid,
+ struct passwd *pPasswd,
+ char *pchBuffer,
+ size_t nBufSize,
+ struct passwd **ppResult
+ );
+}
+#endif /* HAVE_GETPWUID_R */
+
+#endif /* _PAL_IDENTITY_HPP_ */
diff --git a/src/pal/src/include/pal/init.h b/src/pal/src/include/pal/init.h
new file mode 100644
index 0000000000..d478ed275b
--- /dev/null
+++ b/src/pal/src/include/pal/init.h
@@ -0,0 +1,111 @@
+// 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:
+
+ include/pal/init.h
+
+Abstract:
+ Header file for PAL init utility functions. Those functions
+ are only use by the PAL itself.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_INIT_H_
+#define _PAL_INIT_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function:
+ PALCommonCleanup
+
+Utility function to prepare for shutdown.
+
+--*/
+void PALCommonCleanup();
+
+extern Volatile<INT> init_count;
+
+/*++
+MACRO:
+ PALIsInitialized
+
+Returns TRUE if the PAL is in an initialized state
+(#calls to PAL_Initialize > #calls to PAL_Terminate)
+
+Warning : this will only report the PAL's state at the moment it is called.
+If it is necessary to ensure the PAL remains initialized (or not) while doing
+some work, the Initialization lock (PALInitLock()) should be held.
+--*/
+#define PALIsInitialized() (0 < init_count)
+
+/*++
+Function:
+ PALIsThreadDataInitialized
+
+Returns TRUE if startup has reached a point where thread data is available
+--*/
+BOOL
+PALIsThreadDataInitialized();
+
+/*++
+Function:
+ PALIsShuttingDown
+
+Returns TRUE if the some thread has declared intent to shutdown
+--*/
+BOOL
+PALIsShuttingDown();
+
+/*++
+Function:
+ PALSetShutdownIntent
+
+Delcares intent to shutdown
+--*/
+void
+PALSetShutdownIntent();
+
+/*++
+Function:
+ PALInitLock
+
+Take the initializaiton critical section (init_critsec). necessary to serialize
+TerminateProcess along with PAL_Terminate and PAL_Initialize
+
+(no parameters)
+
+Return value :
+ TRUE if critical section existed (and was acquired)
+ FALSE if critical section doens't exist yet
+--*/
+BOOL PALInitLock(void);
+
+/*++
+Function:
+ PALInitUnlock
+
+Release the initialization critical section (init_critsec).
+
+(no parameters, no return value)
+--*/
+void PALInitUnlock(void);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_INIT_H_ */
diff --git a/src/pal/src/include/pal/list.h b/src/pal/src/include/pal/list.h
new file mode 100644
index 0000000000..cd78c0f03a
--- /dev/null
+++ b/src/pal/src/include/pal/list.h
@@ -0,0 +1,141 @@
+// 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:
+
+ list.h
+
+Abstract:
+
+ Doubly-linked list manipulation macros (from ntrtl.h)
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _LIST_H_INCLUDED
+#define _LIST_H_INCLUDED
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+typedef struct _LIST_ENTRY {
+ struct _LIST_ENTRY *Flink;
+ struct _LIST_ENTRY *Blink;
+} LIST_ENTRY, *PLIST_ENTRY;
+
+//
+// VOID
+// InitializeListHead(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define InitializeListHead(ListHead) (\
+ (ListHead)->Flink = (ListHead)->Blink = (ListHead))
+
+//
+// BOOLEAN
+// IsListEmpty(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define IsListEmpty(ListHead) \
+ ((ListHead)->Flink == (ListHead))
+
+//
+// PLIST_ENTRY
+// RemoveHeadList(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define RemoveHeadList(ListHead) \
+ (ListHead)->Flink;\
+ {RemoveEntryList((ListHead)->Flink)}
+
+//
+// PLIST_ENTRY
+// RemoveTailList(
+// PLIST_ENTRY ListHead
+// );
+//
+
+#define RemoveTailList(ListHead) \
+ (ListHead)->Blink;\
+ {RemoveEntryList((ListHead)->Blink)}
+
+//
+// VOID
+// RemoveEntryList(
+// PLIST_ENTRY Entry
+// );
+//
+
+#define RemoveEntryList(Entry) {\
+ PLIST_ENTRY _EX_Blink;\
+ PLIST_ENTRY _EX_Flink;\
+ _EX_Flink = (Entry)->Flink;\
+ _EX_Blink = (Entry)->Blink;\
+ _EX_Blink->Flink = _EX_Flink;\
+ _EX_Flink->Blink = _EX_Blink;\
+ }
+
+//
+// VOID
+// InsertTailList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertTailList(ListHead,Entry) {\
+ PLIST_ENTRY _EX_Blink;\
+ PLIST_ENTRY _EX_ListHead;\
+ _EX_ListHead = (ListHead);\
+ _EX_Blink = _EX_ListHead->Blink;\
+ (Entry)->Flink = _EX_ListHead;\
+ (Entry)->Blink = _EX_Blink;\
+ _EX_Blink->Flink = (Entry);\
+ _EX_ListHead->Blink = (Entry);\
+ }
+
+//
+// VOID
+// InsertHeadList(
+// PLIST_ENTRY ListHead,
+// PLIST_ENTRY Entry
+// );
+//
+
+#define InsertHeadList(ListHead,Entry) {\
+ PLIST_ENTRY _EX_Flink;\
+ PLIST_ENTRY _EX_ListHead;\
+ _EX_ListHead = (ListHead);\
+ _EX_Flink = _EX_ListHead->Flink;\
+ (Entry)->Flink = _EX_Flink;\
+ (Entry)->Blink = _EX_ListHead;\
+ _EX_Flink->Blink = (Entry);\
+ _EX_ListHead->Flink = (Entry);\
+ }
+
+#define CONTAINING_RECORD(address, type, field) ((type *)( \
+ (PCHAR)(address) - \
+ (ULONG_PTR)(&((type *)0)->field)))
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // _LIST_H_INCLUDED
+
diff --git a/src/pal/src/include/pal/locale.h b/src/pal/src/include/pal/locale.h
new file mode 100644
index 0000000000..f59ce2e174
--- /dev/null
+++ b/src/pal/src/include/pal/locale.h
@@ -0,0 +1,75 @@
+// 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:
+
+ locale.h
+
+Abstract:
+
+ Prototypes for codepage initialization, and control of the readwrite locks
+ for systems that use them.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_LOCALE_H_
+#define _PAL_LOCALE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#if HAVE_LOWERCASE_ISO_NAME
+#define ISO_NAME(region, encoding, part) region ".iso" encoding part
+#elif HAVE_UNDERSCORE_ISO_NAME
+#define ISO_NAME(region, encoding, part) region ".ISO_" encoding "-" part
+#else
+#define ISO_NAME(region, encoding, part) region ".ISO" encoding "-" part
+#endif
+
+#if HAVE_COREFOUNDATION
+#define CF_EXCLUDE_CSTD_HEADERS
+#include <CoreFoundation/CoreFoundation.h>
+#endif // HAVE_COREFOUNDATION
+
+#if HAVE_COREFOUNDATION
+#if !ENABLE_DOWNLEVEL_FOR_NLS
+BOOL LocaleInitialize( void );
+void LocaleCleanup( void );
+#endif // !ENABLE_DOWNLEVEL_FOR_NLS
+
+typedef
+struct _CP_MAPPING
+{
+ UINT nCodePage; /* Code page identifier. */
+ CFStringEncoding nCFEncoding; /* The equivalent CFString encoding. */
+ UINT nMaxByteSize; /* The max byte size of any character. */
+ BYTE LeadByte[ MAX_LEADBYTES ]; /* The lead byte array. */
+} CP_MAPPING;
+#elif HAVE_PTHREAD_RWLOCK_T
+typedef
+struct _CP_MAPPING
+{
+ UINT nCodePage; // Code page identifier.
+ LPCSTR lpBSDEquivalent; // The equivalent BSD locale identifier.
+ UINT nMaxByteSize; // The max byte size of any character.
+ BYTE LeadByte[ MAX_LEADBYTES ]; // The lead byte array.
+} CP_MAPPING;
+#else
+#error Insufficient platform support for text encodings
+#endif
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_LOCALE_H_ */
diff --git a/src/pal/src/include/pal/malloc.hpp b/src/pal/src/include/pal/malloc.hpp
new file mode 100644
index 0000000000..c7333419a7
--- /dev/null
+++ b/src/pal/src/include/pal/malloc.hpp
@@ -0,0 +1,152 @@
+// 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:
+
+ pal/malloc.hpp
+
+Abstract:
+ Declarations for suspension safe memory allocation functions
+
+
+
+--*/
+
+#ifndef _MALLOC_HPP
+#define _MALLOC_HPP
+
+#include "pal/corunix.hpp"
+#include "pal/thread.hpp"
+
+#include <stdarg.h>
+#include <stdlib.h>
+
+extern "C"
+{
+ void *
+ __cdecl
+ PAL_realloc(
+ void* pvMemblock,
+ size_t szSize
+ );
+
+ void *
+ __cdecl
+ PAL_malloc(
+ size_t szSize
+ );
+
+ void
+ __cdecl
+ PAL_free(
+ void *pvMem
+ );
+
+ char *
+ __cdecl
+ PAL__strdup(
+ const char *c_szStr
+ );
+}
+
+inline void* operator new(size_t, void* p) throw () { return p; }
+inline void* operator new[](size_t, void* p) throw () { return p; }
+
+namespace CorUnix{
+
+ void *
+ InternalRealloc(
+ void *pvMemblock,
+ size_t szSize
+ );
+
+ void *
+ InternalMalloc(
+ size_t szSize
+ );
+
+ // Define common code for "new" style allocators below.
+#define INTERNAL_NEW_COMMON() \
+ T *pMem = (T*)InternalMalloc(sizeof(T)); \
+ if (pMem == NULL) \
+ return NULL;
+
+ // Define "new" style allocators (which allocate then call a constructor) for different numbers of
+ // constructor arguments. Added based on usage.
+
+ // Default constructor (0 args) case.
+ template<class T>
+ T* InternalNew()
+ {
+ INTERNAL_NEW_COMMON();
+ return new (pMem) T();
+ }
+
+ // 2 args case.
+ template<class T, class A1, class A2>
+ T* InternalNew(A1 arg1, A2 arg2)
+ {
+ INTERNAL_NEW_COMMON();
+ return new (pMem) T(arg1, arg2);
+ }
+
+ // 4 args case.
+ template<class T, class A1, class A2, class A3, class A4>
+ T* InternalNew(A1 arg1, A2 arg2, A3 arg3, A4 arg4)
+ {
+ INTERNAL_NEW_COMMON();
+ return new (pMem) T(arg1, arg2, arg3, arg4);
+ }
+
+ // 5 args case.
+ template<class T, class A1, class A2, class A3, class A4, class A5>
+ T* InternalNew(A1 arg1, A2 arg2, A3 arg3, A4 arg4, A5 arg5)
+ {
+ INTERNAL_NEW_COMMON();
+ return new (pMem) T(arg1, arg2, arg3, arg4, arg5);
+ }
+
+ template<class T> T* InternalNewArray(size_t cElements)
+ {
+ size_t cbSize = (cElements * sizeof(T)) + sizeof(size_t);
+ T *pMem;
+
+ pMem = (T*)InternalMalloc(cbSize);
+
+ if (pMem == NULL)
+ return NULL;
+
+ *(size_t*)pMem = cElements;
+ pMem = (T*)((size_t*)pMem + 1);
+
+ return new (pMem) T[cElements]();
+ }
+
+ template<class T> void InternalDelete(T *p)
+ {
+ if (p)
+ {
+ p->~T();
+ free(p);
+ }
+ }
+
+ template<class T> void InternalDeleteArray(T *p)
+ {
+ if (p)
+ {
+ size_t *pRealMem = (size_t*)p - 1;
+ size_t cElements = *pRealMem;
+ for (size_t i = 0; i < cElements; i++)
+ p[i].~T();
+ free(pRealMem);
+ }
+ }
+}
+
+#endif // _MALLOC_HPP
diff --git a/src/pal/src/include/pal/map.h b/src/pal/src/include/pal/map.h
new file mode 100644
index 0000000000..96f538fbd1
--- /dev/null
+++ b/src/pal/src/include/pal/map.h
@@ -0,0 +1,52 @@
+// 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:
+
+ include/pal/map.h
+
+Abstract:
+
+ Header file for file mapping functions.
+
+
+
+--*/
+
+#ifndef _PAL_MAP_H_
+#define _PAL_MAP_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function :
+ MAPGetRegionInfo
+
+ Parameters:
+ lpAddress: pointer to the starting memory location, not necessary
+ to be rounded to the page location
+
+ lpBuffer: if this function finds information about the specified address,
+ the information is stored in this struct
+
+ Note: This function is to be used in virtual.c
+
+ Returns TRUE if this function finds information about the specified address
+--*/
+
+BOOL MAPGetRegionInfo(LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_MAP_H_ */
+
diff --git a/src/pal/src/include/pal/map.hpp b/src/pal/src/include/pal/map.hpp
new file mode 100644
index 0000000000..854e6c549a
--- /dev/null
+++ b/src/pal/src/include/pal/map.hpp
@@ -0,0 +1,209 @@
+// 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:
+
+ include/pal/map.hpp
+
+Abstract:
+
+ Header file for file mapping functions.
+
+
+
+--*/
+
+#ifndef _PAL_MAP_H_
+#define _PAL_MAP_H_
+
+#include "corunix.hpp"
+#include <sys/param.h>
+
+extern "C"
+{
+#include "list.h"
+
+#ifndef NO_INO
+#define NO_INO ((ino_t)-1)
+#endif
+
+ /*++
+ Function :
+ MapInitialize
+
+ Initialize the critical sections.
+
+ Return value:
+ TRUE if initialization succeeded
+ FALSE otherwise
+ --*/
+ BOOL MAPInitialize( void );
+
+ /*++
+ Function :
+ MapCleanup
+
+ Deletes the critical sections.
+
+ --*/
+ void MAPCleanup( void );
+
+ /*++
+ Function :
+ MAPGetRegionInfo
+
+ Parameters:
+ lpAddress: pointer to the starting memory location, not necessary
+ to be rounded to the page location
+
+ lpBuffer: if this function finds information about the specified address,
+ the information is stored in this struct
+
+ Note: This function is to be used in virtual.c
+
+ Returns TRUE if this function finds information about the specified address
+ --*/
+
+ BOOL MAPGetRegionInfo(LPVOID lpAddress, PMEMORY_BASIC_INFORMATION lpBuffer);
+
+ /*++
+ MAPMapPEFile -
+
+ Map a PE format file into memory like Windows LoadLibrary() would do.
+ Doesn't apply base relocations if the function is relocated.
+
+ Parameters:
+ IN hFile - file to map
+
+ Return value:
+ non-NULL - the base address of the mapped image
+ NULL - error, with last error set.
+ --*/
+
+ void * MAPMapPEFile(HANDLE hFile);
+
+ /*++
+ Function :
+ MAPUnmapPEFile - unmap a PE file, and remove it from the recorded list of PE files mapped
+
+ returns TRUE if successful, FALSE otherwise
+ --*/
+ BOOL MAPUnmapPEFile(LPCVOID lpAddress);
+}
+
+namespace CorUnix
+{
+ extern CObjectType otFileMapping;
+
+#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS
+ typedef struct _NativeMapHolder
+ {
+ Volatile<LONG> ref_count;
+ LPVOID address;
+ SIZE_T size;
+ SIZE_T offset; /* for future use */
+ } NativeMapHolder;
+#endif
+
+ /* Process specific information. This
+ structure is not stored in shared memory.*/
+ typedef struct _MVL
+ {
+ LIST_ENTRY Link;
+
+ //
+ // Each MVL entry holds a reference to its parent file
+ // mapping object.
+ //
+
+ IPalObject *pFileMapping;
+
+#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS
+ NativeMapHolder * pNMHolder; /* Ref-counted holder for memory mapping */
+ dev_t MappedFileDevNum; /* ID of device containing the file to be mapped */
+ ino_t MappedFileInodeNum; /* Inode number of file to be mapped.
+ These two fields are used used to uniquely
+ identify files on systems that do not allow
+ more than one shared mmapping per region of
+ physical file, per process */
+#endif
+ LPVOID lpAddress; /* The pointer to the mapped memory. */
+ SIZE_T NumberOfBytesToMap; /* Number of bytes to map. */
+ DWORD dwDesiredAccess; /* Desired access. */
+ LPVOID lpPEBaseAddress; /* If this mapping is part of a PE file mapping, this is the
+ base address pointer of the PE file (used to find all
+ parts of the PE file mapping to allow PE file unload).
+ Otherwise, it is NULL. */
+ } MAPPED_VIEW_LIST, * PMAPPED_VIEW_LIST;
+
+ class CFileMappingImmutableData
+ {
+ public:
+ CHAR szFileName[MAXPATHLEN];
+ UINT MaxSize; // The max size of the file mapping object
+ DWORD flProtect; // Protection desired for the file view
+ BOOL bPALCreatedTempFile; // TRUE if it's a PAL created file
+ DWORD dwDesiredAccessWhenOpened; // FILE_MAP_WRITE etc
+ };
+
+ class CFileMappingProcessLocalData
+ {
+ public:
+ INT UnixFd; /* File descriptor. */
+
+#if ONE_SHARED_MAPPING_PER_FILEREGION_PER_PROCESS
+ dev_t MappedFileDevNum; /* ID of device containing the file to be mapped */
+ ino_t MappedFileInodeNum; /* Inode number of file to be mapped.
+ These two fields are used used to uniquely
+ identify files on systems that do not allow
+ more than one shared mmapping per region of
+ physical file, per process */
+#endif
+ };
+
+ PAL_ERROR
+ InternalCreateFileMapping(
+ CPalThread *pThread,
+ HANDLE hFile,
+ LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
+ DWORD flProtect,
+ DWORD dwMaximumSizeHigh,
+ DWORD dwMaximumSizeLow,
+ LPCWSTR lpName,
+ HANDLE *phMapping
+ );
+
+ PAL_ERROR
+ InternalOpenFileMapping(
+ CPalThread *pThread,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName,
+ HANDLE *phMapping
+ );
+
+ PAL_ERROR
+ InternalMapViewOfFile(
+ CPalThread *pThread,
+ HANDLE hFileMappingObject,
+ DWORD dwDesiredAccess,
+ DWORD dwFileOffsetHigh,
+ DWORD dwFileOffsetLow,
+ SIZE_T dwNumberOfBytesToMap,
+ LPVOID *ppvBaseAddress
+ );
+
+ PAL_ERROR
+ InternalUnmapViewOfFile(
+ CPalThread *pThread,
+ LPCVOID lpBaseAddress
+ );
+
+}
+
+#endif /* _PAL_MAP_H_ */
diff --git a/src/pal/src/include/pal/misc.h b/src/pal/src/include/pal/misc.h
new file mode 100644
index 0000000000..65d59aee60
--- /dev/null
+++ b/src/pal/src/include/pal/misc.h
@@ -0,0 +1,83 @@
+// 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:
+
+ include/pal/misc.h
+
+Abstract:
+ Header file for the initialization and clean up functions
+ for the misc Win32 functions
+
+
+
+--*/
+
+#ifndef __MISC_H_
+#define __MISC_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function :
+
+ PAL_rand
+
+ Calls rand and mitigates the difference between RAND_MAX
+ on Windows and FreeBSD.
+--*/
+int __cdecl PAL_rand(void);
+
+/*++
+Function :
+
+ PAL_time
+--*/
+PAL_time_t __cdecl PAL_time(PAL_time_t*);
+
+/*++
+Function:
+TIMEInitialize
+
+Return value:
+TRUE if initialize succeeded
+FALSE otherwise
+
+--*/
+BOOL TIMEInitialize( void );
+
+/*++
+Function :
+ MsgBoxInitialize
+
+ Initialize the critical sections.
+
+Return value:
+ TRUE if initialize succeeded
+ FALSE otherwise
+
+--*/
+BOOL MsgBoxInitialize( void );
+
+/*++
+Function :
+ MsgBoxCleanup
+
+ Deletes the critical sections.
+
+--*/
+void MsgBoxCleanup( void );
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* __MISC_H_ */
diff --git a/src/pal/src/include/pal/module.h b/src/pal/src/include/pal/module.h
new file mode 100644
index 0000000000..95fa605c21
--- /dev/null
+++ b/src/pal/src/include/pal/module.h
@@ -0,0 +1,203 @@
+// 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:
+
+ include/pal/module.h
+
+Abstract:
+ Header file for modle management utilities.
+
+
+
+--*/
+
+#ifndef _PAL_MODULE_H_
+#define _PAL_MODULE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+typedef BOOL (__stdcall *PDLLMAIN)(HINSTANCE, DWORD, LPVOID); /* entry point of module */
+typedef HINSTANCE (PALAPI *PREGISTER_MODULE)(LPCSTR); /* used to create the HINSTANCE for above DLLMain entry point */
+typedef VOID (PALAPI *PUNREGISTER_MODULE)(HINSTANCE); /* used to cleanup the HINSTANCE for above DLLMain entry point */
+
+typedef struct _MODSTRUCT
+{
+ HMODULE self; /* circular reference to this module */
+ void *dl_handle; /* handle returned by dlopen() */
+ HINSTANCE hinstance; /* handle returned by PAL_RegisterLibrary */
+ LPWSTR lib_name; /* full path of module */
+ INT refcount; /* reference count */
+ /* -1 means infinite reference count - module is never released */
+ BOOL threadLibCalls; /* TRUE for DLL_THREAD_ATTACH/DETACH notifications enabled, FALSE if they are disabled */
+
+#if RETURNS_NEW_HANDLES_ON_REPEAT_DLOPEN
+ ino_t inode;
+ dev_t device;
+#endif
+
+ PDLLMAIN pDllMain; /* entry point of module */
+
+ /* reference to next and previous modules in list (in load order) */
+ struct _MODSTRUCT *next;
+ struct _MODSTRUCT *prev;
+} MODSTRUCT;
+
+
+/*++
+Function :
+ LOADInitializeModules
+
+ Initialize the process-wide list of modules
+
+Parameters :
+ None
+
+Return value :
+ TRUE on success, FALSE on failure
+
+--*/
+BOOL LOADInitializeModules();
+
+/*++
+Function :
+ LOADSetExeName
+
+ Set the exe name path
+
+Parameters :
+ LPWSTR man exe path and name
+
+Return value :
+ TRUE if initialization succeedded
+ FALSE otherwise
+
+--*/
+BOOL LOADSetExeName(LPWSTR name);
+
+/*++
+Function :
+ LOADCallDllMain
+
+ Call DllMain for all modules (that have one) with the given "fwReason"
+
+Parameters :
+ DWORD dwReason : parameter to pass down to DllMain, one of DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH,
+ DLL_THREAD_ATTACH, DLL_THREAD_DETACH
+
+ LPVOID lpReserved : parameter to pass down to DllMain
+ If dwReason is DLL_PROCESS_ATTACH, lpvReserved is NULL for dynamic loads and non-NULL for static loads.
+ If dwReason is DLL_PROCESS_DETACH, lpvReserved is NULL if DllMain has been called by using FreeLibrary
+ and non-NULL if DllMain has been called during process termination.
+
+(no return value)
+
+Notes :
+ This is used to send DLL_THREAD_*TACH messages to modules
+--*/
+void LOADCallDllMain(DWORD dwReason, LPVOID lpReserved);
+
+/*++
+Function:
+ LockModuleList
+
+Abstract
+ Enter the critical section associated to the module list
+
+Parameter
+ void
+
+Return
+ void
+--*/
+void LockModuleList();
+
+/*++
+Function:
+ UnlockModuleList
+
+Abstract
+ Leave the critical section associated to the module list
+
+Parameter
+ void
+
+Return
+ void
+--*/
+void UnlockModuleList();
+
+/*++
+Function:
+ PAL_LOADLoadPEFile
+
+Abstract
+ Loads a PE file into memory. Properly maps all of the sections in the PE file. Returns a pointer to the
+ loaded base.
+
+Parameters:
+ IN hFile - The file to load
+
+Return value:
+ A valid base address if successful.
+ 0 if failure
+--*/
+void * PAL_LOADLoadPEFile(HANDLE hFile);
+
+/*++
+ PAL_LOADUnloadPEFile
+
+ Unload a PE file that was loaded by PAL_LOADLoadPEFile().
+
+Parameters:
+ IN ptr - the file pointer returned by PAL_LOADLoadPEFile()
+
+Return value:
+ TRUE - success
+ FALSE - failure (incorrect ptr, etc.)
+--*/
+BOOL PAL_LOADUnloadPEFile(void * ptr);
+
+/*++
+ LOADInitializeCoreCLRModule
+
+ Run the initialization methods for CoreCLR module.
+
+Parameters:
+ None
+
+Return value:
+ TRUE if successful
+ FALSE if failure
+--*/
+BOOL LOADInitializeCoreCLRModule();
+
+/*++
+Function :
+ LOADGetPalLibrary
+
+ Load and initialize the PAL module.
+
+Parameters :
+ None
+
+Return value :
+ handle to loaded module
+
+--*/
+MODSTRUCT *LOADGetPalLibrary();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_MODULE_H_ */
+
diff --git a/src/pal/src/include/pal/modulename.h b/src/pal/src/include/pal/modulename.h
new file mode 100644
index 0000000000..70b0a610dc
--- /dev/null
+++ b/src/pal/src/include/pal/modulename.h
@@ -0,0 +1,39 @@
+// 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:
+
+ include/pal/modulename.h
+
+Abstract:
+ Header file for functions to get the name of a module
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_MODULENAME_H_
+#define _PAL_MODULENAME_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+const char *PAL_dladdr(LPVOID ProcAddress);
+#if defined(_AIX)
+int GetLibRotorNameViaLoadQuery(LPSTR pszBuf);
+#endif
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /*_PAL_MODULENAME_H_*/
diff --git a/src/pal/src/include/pal/mutex.hpp b/src/pal/src/include/pal/mutex.hpp
new file mode 100644
index 0000000000..6a46689d7d
--- /dev/null
+++ b/src/pal/src/include/pal/mutex.hpp
@@ -0,0 +1,191 @@
+// 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:
+
+ mutex.hpp
+
+Abstract:
+
+ Mutex object structure definition.
+
+
+
+--*/
+
+#ifndef _PAL_MUTEX_H_
+#define _PAL_MUTEX_H_
+
+#include "corunix.hpp"
+#include "sharedmemory.h"
+
+#include <pthread.h>
+
+namespace CorUnix
+{
+ extern CObjectType otMutex;
+ extern CObjectType otNamedMutex;
+
+ PAL_ERROR
+ InternalCreateMutex(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpMutexAttributes,
+ BOOL bInitialOwner,
+ LPCSTR lpName,
+ HANDLE *phMutex
+ );
+
+ PAL_ERROR
+ InternalReleaseMutex(
+ CPalThread *pThread,
+ HANDLE hMutex
+ );
+
+ PAL_ERROR
+ InternalOpenMutex(
+ CPalThread *pThread,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCSTR lpName,
+ HANDLE *phMutex
+ );
+
+}
+
+#define SYNCSPINLOCK_F_ASYMMETRIC 1
+
+#define SPINLOCKInit(lock) (*(lock) = 0)
+#define SPINLOCKDestroy SPINLOCKInit
+
+void SPINLOCKAcquire (LONG * lock, unsigned int flags);
+void SPINLOCKRelease (LONG * lock);
+DWORD SPINLOCKTryAcquire (LONG * lock);
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Named mutex
+
+// Temporarily disabling usage of pthread process-shared mutexes on ARM/ARM64 due to functional issues that cannot easily be
+// detected with code due to hangs. See https://github.com/dotnet/coreclr/issues/5456.
+#if HAVE_FULLY_FEATURED_PTHREAD_MUTEXES && HAVE_FUNCTIONAL_PTHREAD_ROBUST_MUTEXES && !(defined(_ARM_) || defined(_ARM64_))
+ #define NAMED_MUTEX_USE_PTHREAD_MUTEX 1
+#else
+ #define NAMED_MUTEX_USE_PTHREAD_MUTEX 0
+#endif
+
+enum class NamedMutexError : DWORD
+{
+ MaximumRecursiveLocksReached = ERROR_NOT_ENOUGH_MEMORY,
+ ThreadHasNotAcquiredMutex = ERROR_NOT_OWNER,
+ Unknown = ERROR_NOT_ENOUGH_MEMORY
+};
+
+enum class MutexTryAcquireLockResult
+{
+ AcquiredLock,
+ AcquiredLockButMutexWasAbandoned,
+ TimedOut
+};
+
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+class MutexHelpers
+{
+public:
+ static void InitializeProcessSharedRobustRecursiveMutex(pthread_mutex_t *mutex);
+ static void DestroyMutex(pthread_mutex_t *mutex);
+
+ static MutexTryAcquireLockResult TryAcquireLock(pthread_mutex_t *mutex, DWORD timeoutMilliseconds);
+ static void ReleaseLock(pthread_mutex_t *mutex);
+};
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+
+class NamedMutexSharedData
+{
+private:
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+ pthread_mutex_t m_lock;
+#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ UINT32 m_timedWaiterCount;
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+ UINT32 m_lockOwnerProcessId;
+ UINT64 m_lockOwnerThreadId;
+ bool m_isAbandoned;
+
+public:
+ NamedMutexSharedData();
+ ~NamedMutexSharedData();
+
+#if NAMED_MUTEX_USE_PTHREAD_MUTEX
+public:
+ pthread_mutex_t *GetLock();
+#else // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+public:
+ bool HasAnyTimedWaiters() const;
+ void IncTimedWaiterCount();
+ void DecTimedWaiterCount();
+#endif // NAMED_MUTEX_USE_PTHREAD_MUTEX
+
+public:
+ bool IsAbandoned() const;
+ void SetIsAbandoned(bool isAbandoned);
+
+public:
+ bool IsLockOwnedByAnyThread() const;
+ bool IsLockOwnedByCurrentThread() const;
+ void SetLockOwnerToCurrentThread();
+ void ClearLockOwner();
+};
+
+class NamedMutexProcessData : public SharedMemoryProcessDataBase
+{
+private:
+ static const UINT8 SyncSystemVersion;
+ static const DWORD PollLoopMaximumSleepMilliseconds;
+
+private:
+ SharedMemoryProcessDataHeader *m_processDataHeader;
+ NamedMutexSharedData *m_sharedData;
+ SIZE_T m_lockCount;
+#if !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ HANDLE m_processLockHandle;
+ int m_sharedLockFileDescriptor;
+#endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ CorUnix::CPalThread *m_lockOwnerThread;
+ NamedMutexProcessData *m_nextInThreadOwnedNamedMutexList;
+
+public:
+ static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool acquireLockIfCreated, bool *createdRef);
+ static SharedMemoryProcessDataHeader *Open(LPCSTR name);
+private:
+ static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, bool createIfNotExist, bool acquireLockIfCreated, bool *createdRef);
+
+public:
+ NamedMutexProcessData(
+ SharedMemoryProcessDataHeader *processDataHeader
+ #if !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ ,
+ int sharedLockFileDescriptor
+ #endif // !NAMED_MUTEX_USE_PTHREAD_MUTEX
+ );
+ virtual void Close(bool isAbruptShutdown, bool releaseSharedData) override;
+
+private:
+ NamedMutexSharedData *GetSharedData() const;
+ void SetLockOwnerThread(CorUnix::CPalThread *lockOwnerThread);
+public:
+ NamedMutexProcessData *GetNextInThreadOwnedNamedMutexList() const;
+ void SetNextInThreadOwnedNamedMutexList(NamedMutexProcessData *next);
+
+public:
+ MutexTryAcquireLockResult TryAcquireLock(DWORD timeoutMilliseconds);
+ void ReleaseLock();
+ void Abandon();
+private:
+ void ActuallyReleaseLock();
+};
+
+#endif //_PAL_MUTEX_H_
diff --git a/src/pal/src/include/pal/palinternal.h b/src/pal/src/include/pal/palinternal.h
new file mode 100644
index 0000000000..7348192e6d
--- /dev/null
+++ b/src/pal/src/include/pal/palinternal.h
@@ -0,0 +1,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_ */
diff --git a/src/pal/src/include/pal/perftrace.h b/src/pal/src/include/pal/perftrace.h
new file mode 100644
index 0000000000..fec46e2330
--- /dev/null
+++ b/src/pal/src/include/pal/perftrace.h
@@ -0,0 +1,70 @@
+// 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:
+
+ include/pal/perftrace.h
+
+Abstract:
+ Header file for PAL Performance trace utilities.
+
+
+
+--*/
+
+/*
+Overview of PAL Performance utilities
+
+ */
+
+#ifndef _PAL_PERFTRACE_H_
+#define _PAL_PERFTRACE_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#if PAL_PERF
+#define PERF_ENTRY(x) \
+ ULONGLONG pal_perf_start_tick = 0;\
+ PERFLogFunctionEntry( PAL_PERF_##x, &pal_perf_start_tick )
+#define PERF_EXIT(x) \
+ PERFLogFunctionExit( PAL_PERF_##x, &pal_perf_start_tick )
+#define PERF_ENTRY_ONLY(x) \
+ PERFNoLatencyProfileEntry( PAL_PERF_##x )
+
+BOOL PERFInitialize(LPWSTR command_line, LPWSTR exe_path) ;
+void PERFTerminate( );
+BOOL PERFAllocThreadInfo( );
+void PERFLogFunctionExit(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick);
+void PERFLogFunctionEntry(unsigned int pal_api_id, ULONGLONG *pal_perf_start_tick);
+void PERFEnableThreadProfile(BOOL isInternal);
+void PERFDisableThreadProfile(BOOL isInternal);
+void PERFEnableProcessProfile( );
+void PERFDisableProcessProfile( );
+BOOL PERFIsProcessProfileEnabled( );
+void PERFNoLatencyProfileEntry(unsigned int pal_api_id );
+void PERFCalibrate(const char* msg);
+
+#else /* PAL_PERF */
+
+#define PERF_ENTRY(x)
+#define PERF_ENTRY_ONLY(x)
+#define PERF_EXIT(x)
+
+#endif /* PAL_PERF */
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_PERFTRACE_H_ */
+
+
+
diff --git a/src/pal/src/include/pal/printfcpp.hpp b/src/pal/src/include/pal/printfcpp.hpp
new file mode 100644
index 0000000000..0a728c9fd7
--- /dev/null
+++ b/src/pal/src/include/pal/printfcpp.hpp
@@ -0,0 +1,133 @@
+// 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:
+
+ pal/printfcpp.hpp
+
+Abstract:
+ Declarations for suspension safe memory allocation functions
+
+
+
+--*/
+
+#ifndef _PRINTFCPP_HPP
+#define _PRINTFCPP_HPP
+
+#ifdef __cplusplus
+#include "pal/threadinfo.hpp"
+#endif
+
+#include <stdarg.h>
+
+#ifdef __cplusplus
+typedef char16_t wchar_16; // __wchar_16_cpp (which is defined in palinternal.h) needs to be redefined to wchar_16.
+
+extern "C"
+{
+ int
+ __cdecl
+ PAL__vsnprintf(
+ LPSTR Buffer,
+ size_t Count,
+ LPCSTR Format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL__wvsnprintf(
+ LPWSTR Buffer,
+ size_t Count,
+ LPCWSTR Format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL_vfprintf(
+ PAL_FILE *stream,
+ const char *format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL_vfwprintf(
+ PAL_FILE *stream,
+ const wchar_16 *format,
+ va_list ap);
+}
+
+namespace CorUnix
+{
+ int
+ InternalVfprintf(
+ CPalThread *pthrCurrent,
+ PAL_FILE *stream,
+ const char *format,
+ va_list ap);
+
+ int
+ InternalWvsnprintf(
+ CPalThread *pthrCurrent,
+ LPWSTR Buffer,
+ size_t Count,
+ LPCWSTR Format,
+ va_list ap);
+
+ int
+ InternalVsnprintf(
+ CPalThread *pthrCurrent,
+ LPSTR Buffer,
+ size_t Count,
+ LPCSTR Format,
+ va_list ap);
+
+ int
+ InternalVfwprintf(
+ CPalThread *pthrCurrent,
+ PAL_FILE *stream,
+ const wchar_16 *format,
+ va_list ap);
+
+}
+#else // __cplusplus
+
+ int
+ __cdecl
+ PAL__vsnprintf(
+ LPSTR Buffer,
+ size_t Count,
+ LPCSTR Format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL__wvsnprintf(
+ LPWSTR Buffer,
+ size_t Count,
+ LPCWSTR Format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL_vfprintf(
+ PAL_FILE *stream,
+ const char *format,
+ va_list ap);
+
+ int
+ __cdecl
+ PAL_vfwprintf(
+ PAL_FILE *stream,
+ const wchar_16 *format,
+ va_list ap);
+
+#endif // __cplusplus
+
+#endif // _PRINTFCPP_HPP
+
diff --git a/src/pal/src/include/pal/process.h b/src/pal/src/include/pal/process.h
new file mode 100644
index 0000000000..990aec5b21
--- /dev/null
+++ b/src/pal/src/include/pal/process.h
@@ -0,0 +1,162 @@
+// 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:
+
+ include/pal/process.h
+
+Abstract:
+
+ Miscellaneous process related functions.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_PROCESS_H_
+#define _PAL_PROCESS_H_
+
+#include "pal/palinternal.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/* thread ID of thread that has initiated an ExitProcess (or TerminateProcess).
+ this is to make sure only one thread cleans up the PAL, and also to prevent
+ calls to CreateThread from succeeding once shutdown has started
+ [defined in process.c]
+*/
+extern Volatile<LONG> terminator;
+
+// The process and session ID of this process, so we can avoid excessive calls to getpid() and getsid().
+extern DWORD gPID;
+extern DWORD gSID;
+
+extern LPWSTR pAppDir;
+
+/*++
+Function:
+ PROCGetProcessIDFromHandle
+
+Abstract
+ Return the process ID from a process handle
+--*/
+DWORD PROCGetProcessIDFromHandle(HANDLE hProcess);
+
+/*++
+Function:
+ PROCCreateInitialProcess
+
+Abstract
+ Initialize all the structures for the initial process.
+
+Parameter
+ lpwstrCmdLine: Command line.
+ lpwstrFullPath : Full path to executable
+
+Return
+ TRUE: if successful
+ FALSE: otherwise
+
+Notes :
+ This function takes ownership of lpwstrCmdLine, but not of lpwstrFullPath
+--*/
+BOOL PROCCreateInitialProcess(LPWSTR lpwstrCmdLine, LPWSTR lpwstrFullPath);
+
+/*++
+Function:
+ PROCCleanupInitialProcess
+
+Abstract
+ Cleanup all the structures for the initial process.
+
+Parameter
+ VOID
+
+Return
+ VOID
+
+--*/
+VOID PROCCleanupInitialProcess(VOID);
+
+#if USE_SYSV_SEMAPHORES
+/*++
+Function:
+ PROCCleanupThreadSemIds(VOID);
+
+Abstract
+ Cleanup SysV semaphore ids for all threads.
+
+(no parameters, no return value)
+--*/
+VOID PROCCleanupThreadSemIds(VOID);
+#endif
+
+/*++
+Function:
+ PROCProcessLock
+
+Abstract
+ Enter the critical section associated to the current process
+--*/
+VOID PROCProcessLock(VOID);
+
+
+/*++
+Function:
+ PROCProcessUnlock
+
+Abstract
+ Leave the critical section associated to the current process
+--*/
+VOID PROCProcessUnlock(VOID);
+
+/*++
+Function:
+ PROCAbort()
+
+ Aborts the process after calling the shutdown cleanup handler. This function
+ should be called instead of calling abort() directly.
+
+ Does not return
+--*/
+PAL_NORETURN
+void PROCAbort();
+
+/*++
+Function:
+ PROCNotifyProcessShutdown
+
+ Calls the abort handler to do any shutdown cleanup. Call be
+ called from the unhandled native exception handler.
+
+(no return value)
+--*/
+void PROCNotifyProcessShutdown();
+
+/*++
+Function:
+ InitializeFlushProcessWriteBuffers
+
+Abstract
+ This function initializes data structures needed for the FlushProcessWriteBuffers
+Return
+ TRUE if it succeeded, FALSE otherwise
+--*/
+BOOL InitializeFlushProcessWriteBuffers();
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //PAL_PROCESS_H_
+
diff --git a/src/pal/src/include/pal/procobj.hpp b/src/pal/src/include/pal/procobj.hpp
new file mode 100644
index 0000000000..a75c764246
--- /dev/null
+++ b/src/pal/src/include/pal/procobj.hpp
@@ -0,0 +1,125 @@
+// 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:
+
+ include/pal/procobj.hpp
+
+Abstract:
+ Header file for process structures
+
+
+
+--*/
+
+#ifndef _PAL_PROCOBJ_HPP_
+#define _PAL_PROCOBJ_HPP_
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+ extern CObjectType otProcess;
+
+ typedef enum
+ {
+ PS_IDLE,
+ PS_STARTING,
+ PS_RUNNING,
+ PS_DONE
+ } PROCESS_STATE;
+
+ //
+ // Struct for process module list (EnumProcessModules)
+ //
+ struct ProcessModules
+ {
+ ProcessModules *Next;
+ PVOID BaseAddress;
+ CHAR Name[0];
+ };
+
+ //
+ // Ideally dwProcessId would be part of the process object's immutable
+ // data. Doing so, though, creates complications in CreateProcess. The
+ // contents of the immutable data for a new object must be set before
+ // that object is registered with the object manager (as the object
+ // manager may make a copy of the immutable data). The PID for a new
+ // process, though, is not known until after creation. Registering the
+ // process object after process creation creates an undesirable error path
+ // -- if we are not able to register the process object (say, because of
+ // a low resource condition) we would be forced to return an error to
+ // the caller of CreateProcess, even though the new process was actually
+ // created...
+ //
+ // Note: we could work around this by effectively always going down
+ // the create suspended path. That is, the new process would not exec until
+ // the parent process released it. It's unclear how much benefit this would
+ // provide us.
+ //
+
+ class CProcProcessLocalData
+ {
+ public:
+ CProcProcessLocalData()
+ :
+ dwProcessId(0),
+ ps(PS_IDLE),
+ dwExitCode(0),
+ lAttachCount(0),
+ pProcessModules(NULL),
+ cProcessModules(0)
+ {
+ };
+
+ ~CProcProcessLocalData();
+
+ DWORD dwProcessId;
+ PROCESS_STATE ps;
+ DWORD dwExitCode;
+ LONG lAttachCount;
+ ProcessModules *pProcessModules;
+ DWORD cProcessModules;
+ };
+
+ PAL_ERROR
+ InternalCreateProcess(
+ CPalThread *pThread,
+ LPCWSTR lpApplicationName,
+ LPWSTR lpCommandLine,
+ LPSECURITY_ATTRIBUTES lpProcessAttributes,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ BOOL bInheritHandles,
+ DWORD dwCreationFlags,
+ LPVOID lpEnvironment,
+ LPCWSTR lpCurrentDirectory,
+ LPSTARTUPINFOW lpStartupInfo,
+ LPPROCESS_INFORMATION lpProcessInformation
+ );
+
+ PAL_ERROR
+ InitializeProcessData(
+ void
+ );
+
+ PAL_ERROR
+ InitializeProcessCommandLine(
+ LPWSTR lpwstrCmdLine,
+ LPWSTR lpwstrFullPath
+ );
+
+ PAL_ERROR
+ CreateInitialProcessAndThreadObjects(
+ CPalThread *pThread
+ );
+
+ extern IPalObject *g_pobjProcess;
+}
+
+#endif // _PAL_PROCOBJ_HPP_
+
diff --git a/src/pal/src/include/pal/seh.hpp b/src/pal/src/include/pal/seh.hpp
new file mode 100644
index 0000000000..3ac93d655a
--- /dev/null
+++ b/src/pal/src/include/pal/seh.hpp
@@ -0,0 +1,185 @@
+// 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:
+
+ include/pal/seh.hpp
+
+Abstract:
+ Header file for public Structured Exception Handling stuff
+
+
+
+--*/
+
+#ifndef _PAL_SEH_HPP_
+#define _PAL_SEH_HPP_
+
+#include "config.h"
+#include "pal/palinternal.h"
+#include "pal/corunix.hpp"
+
+// Uncomment this define to turn off the signal handling thread.
+// #define DO_NOT_USE_SIGNAL_HANDLING_THREAD
+
+/*++
+Function :
+ SEHInitialize
+
+ Initialize all SEH-related stuff (signals, etc)
+
+Parameters:
+ CPalThread * pthrCurrent : reference to the current thread.
+ flags : PAL initialize flags
+
+Return value:
+ TRUE if SEH support initialization succeeded,
+ FALSE otherwise
+
+--*/
+BOOL
+SEHInitialize(CorUnix::CPalThread *pthrCurrent, DWORD flags);
+
+/*++
+Function :
+ SEHCleanup
+
+ Clean up SEH-related stuff(signals, etc)
+
+Parameters:
+ None
+
+ (no return value)
+--*/
+VOID
+SEHCleanup();
+
+/*++
+Function:
+ SEHProcessException
+
+ Send the PAL exception to any handler registered.
+
+Parameters:
+ PAL_SEHException* exception
+
+Return value:
+ Returns TRUE if the exception happened in managed code and the execution should
+ continue (with possibly modified context).
+ Returns FALSE if the exception happened in managed code and it was not handled.
+ In case the exception was handled by calling a catch handler, it doesn't return at all.
+--*/
+BOOL
+SEHProcessException(PAL_SEHException* exception);
+
+/*++
+Function:
+ AllocateExceptionRecords
+
+Parameters:
+ exceptionRecord - output pointer to the allocated Windows exception record
+ contextRecord - output pointer to the allocated Windows context record
+--*/
+VOID
+AllocateExceptionRecords(EXCEPTION_RECORD** exceptionRecord, CONTEXT** contextRecord);
+
+#if !HAVE_MACH_EXCEPTIONS
+// TODO: Implement for Mach exceptions. Not in CoreCLR surface area.
+/*++
+Function :
+ SEHHandleControlEvent
+
+ handle Control-C and Control-Break events (call handler routines,
+ notify debugger)
+
+Parameters :
+ DWORD event : event that occurred
+ LPVOID eip : instruction pointer when exception occurred
+
+(no return value)
+
+Notes :
+ Handlers are called on a last-installed, first called basis, until a
+ handler returns TRUE. If no handler returns TRUE (or no hanlder is
+ installed), the default behavior is to call ExitProcess
+--*/
+void SEHHandleControlEvent(DWORD event, LPVOID eip);
+#endif // !HAVE_MACH_EXCEPTIONS
+
+#if !HAVE_MACH_EXCEPTIONS
+/*++
+Function :
+ SEHSetSafeState
+
+ specify whether the current thread is in a state where exception handling
+ of signals can be done safely
+
+Parameters:
+ CPalThread * pthrCurrent : reference to the current thread.
+ BOOL state : TRUE if the thread is safe, FALSE otherwise
+
+(no return value)
+--*/
+void SEHSetSafeState(CorUnix::CPalThread *pthrCurrent, BOOL state);
+
+/*++
+Function :
+ SEHGetSafeState
+
+ determine whether the current thread is in a state where exception handling
+ of signals can be done safely
+
+Parameters:
+ CPalThread * pthrCurrent : reference to the current thread.
+
+Return value :
+ TRUE if the thread is in a safe state, FALSE otherwise
+--*/
+BOOL SEHGetSafeState(CorUnix::CPalThread *pthrCurrent);
+#endif // !HAVE_MACH_EXCEPTIONS
+
+extern "C"
+{
+
+#ifdef FEATURE_PAL_SXS
+/*++
+Function :
+ SEHEnable
+
+ Enable SEH-related stuff on this thread
+
+Parameters:
+ CPalThread * pthrCurrent : reference to the current thread.
+
+Return value :
+ ERROR_SUCCESS, if enabling succeeded
+ an error code, otherwise
+--*/
+CorUnix::PAL_ERROR SEHEnable(CorUnix::CPalThread *pthrCurrent);
+
+/*++
+Function :
+ SEHDisable
+
+ Disable SEH-related stuff on this thread
+
+Parameters:
+ CPalThread * pthrCurrent : reference to the current thread.
+
+Return value :
+ ERROR_SUCCESS, if enabling succeeded
+ an error code, otherwise
+--*/
+CorUnix::PAL_ERROR SEHDisable(CorUnix::CPalThread *pthrCurrent);
+
+#endif // FEATURE_PAL_SXS
+
+}
+
+#endif /* _PAL_SEH_HPP_ */
+
diff --git a/src/pal/src/include/pal/semaphore.hpp b/src/pal/src/include/pal/semaphore.hpp
new file mode 100644
index 0000000000..2943d61c3d
--- /dev/null
+++ b/src/pal/src/include/pal/semaphore.hpp
@@ -0,0 +1,74 @@
+// 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:
+
+ semaphore.hpp
+
+Abstract:
+
+ Semaphore object structure definition.
+
+
+
+--*/
+
+#ifndef _PAL_SEMAPHORE_H_
+#define _PAL_SEMAPHORE_H_
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+ extern CObjectType otSemaphore;
+
+ typedef struct
+ {
+ LONG lMaximumCount;
+ } SemaphoreImmutableData;
+
+ PAL_ERROR
+ InternalCreateSemaphore(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
+ LONG lInitialCount,
+ LONG lMaximumCount,
+ LPCWSTR lpName,
+ HANDLE *phSemaphore
+ );
+
+ PAL_ERROR
+ InternalReleaseSemaphore(
+ CPalThread *pThread,
+ HANDLE hSemaphore,
+ LONG lReleaseCount,
+ LPLONG lpPreviousCount
+ );
+
+ PAL_ERROR
+ InternalOpenSemaphore(
+ CPalThread *pThread,
+ DWORD dwDesiredAccess,
+ BOOL bInheritHandle,
+ LPCWSTR lpName,
+ HANDLE *phSemaphore
+ );
+
+}
+
+#endif //_PAL_SEMAPHORE_H_
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pal/src/include/pal/sharedmemory.h b/src/pal/src/include/pal/sharedmemory.h
new file mode 100644
index 0000000000..45cc4b2c8d
--- /dev/null
+++ b/src/pal/src/include/pal/sharedmemory.h
@@ -0,0 +1,268 @@
+// 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.
+
+#ifndef _PAL_SHARED_MEMORY_H_
+#define _PAL_SHARED_MEMORY_H_
+
+#include "corunix.hpp"
+
+#ifndef static_assert_no_msg
+#define static_assert_no_msg( cond ) static_assert( cond, #cond )
+#endif // !static_assert_no_msg
+
+#ifndef _countof
+#define _countof(a) (sizeof(a) / sizeof(a[0]))
+#endif // !_countof
+
+// - Global shared memory files go in:
+// /tmp/.dotnet/shm/global/<fileName>
+// - Session-scoped shared memory files go in:
+// /tmp/.dotnet/shm/session<sessionId>/<fileName>
+// - Lock files associated with global shared memory files go in:
+// /tmp/.dotnet/lockfiles/global/<fileName>
+// - Lock files associated with session-scoped shared memory files go in:
+// /tmp/.dotnet/lockfiles/session<sessionId>/<fileName>
+
+#define SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT (_MAX_FNAME - 1)
+#define SHARED_MEMORY_MAX_NAME_CHAR_COUNT (_countof("Global\\") - 1 + SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT)
+
+#define SHARED_MEMORY_TEMP_DIRECTORY_PATH "/tmp"
+#define SHARED_MEMORY_RUNTIME_TEMP_DIRECTORY_PATH "/tmp/.dotnet"
+
+#define SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH "/tmp/.dotnet/shm"
+#define SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH "/tmp/.dotnet/lockfiles"
+static_assert_no_msg(_countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH) >= _countof(SHARED_MEMORY_SHARED_MEMORY_DIRECTORY_PATH));
+
+#define SHARED_MEMORY_GLOBAL_DIRECTORY_NAME "global"
+#define SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX "session"
+static_assert_no_msg(_countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) >= _countof(SHARED_MEMORY_GLOBAL_DIRECTORY_NAME));
+
+#define SHARED_MEMORY_UNIQUE_TEMP_NAME_TEMPLATE "/tmp/.coreclr.XXXXXX"
+
+#define SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT (10)
+
+#define SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT \
+ ( \
+ _countof(SHARED_MEMORY_LOCK_FILES_DIRECTORY_PATH) - 1 + \
+ 1 /* path separator */ + \
+ _countof(SHARED_MEMORY_SESSION_DIRECTORY_NAME_PREFIX) - 1 + \
+ SHARED_MEMORY_MAX_SESSION_ID_CHAR_COUNT + \
+ 1 /* path separator */ + \
+ SHARED_MEMORY_MAX_FILE_NAME_CHAR_COUNT \
+ )
+static_assert_no_msg(SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1 /* null terminator */ <= MAX_LONGPATH);
+
+class AutoFreeBuffer
+{
+private:
+ void *m_buffer;
+ bool m_cancel;
+
+public:
+ AutoFreeBuffer(void *buffer);
+ ~AutoFreeBuffer();
+
+public:
+ void Cancel();
+};
+
+enum class SharedMemoryError : DWORD
+{
+ NameEmpty = ERROR_INVALID_PARAMETER,
+ NameTooLong = ERROR_FILENAME_EXCED_RANGE,
+ NameInvalid = ERROR_INVALID_NAME,
+ HeaderMismatch = ERROR_INVALID_HANDLE,
+ OutOfMemory = ERROR_NOT_ENOUGH_MEMORY,
+ IO = ERROR_OPEN_FAILED
+};
+
+class SharedMemoryException
+{
+private:
+ DWORD m_errorCode;
+
+public:
+ SharedMemoryException(DWORD errorCode);
+ DWORD GetErrorCode() const;
+};
+
+class SharedMemoryHelpers
+{
+private:
+ static const mode_t PermissionsMask_AllUsers_ReadWrite;
+ static const mode_t PermissionsMask_AllUsers_ReadWriteExecute;
+public:
+ static const UINT32 InvalidProcessId;
+ static const SIZE_T InvalidThreadId;
+ static const UINT64 InvalidSharedThreadId;
+
+public:
+ static SIZE_T AlignDown(SIZE_T value, SIZE_T alignment);
+ static SIZE_T AlignUp(SIZE_T value, SIZE_T alignment);
+
+ static void *Alloc(SIZE_T byteCount);
+
+ template<SIZE_T DestinationByteCount, SIZE_T SourceByteCount> static SIZE_T CopyString(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, const char (&source)[SourceByteCount]);
+ template<SIZE_T DestinationByteCount> static SIZE_T CopyString(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, LPCSTR source, SIZE_T sourceCharCount);
+ template<SIZE_T DestinationByteCount> static SIZE_T AppendUInt32String(char (&destination)[DestinationByteCount], SIZE_T destinationStartOffset, UINT32 value);
+
+ static bool EnsureDirectoryExists(const char *path, bool isGlobalLockAcquired, bool createIfNotExist = true);
+private:
+ static int Open(LPCSTR path, int flags, mode_t mode = static_cast<mode_t>(0));
+public:
+ static int OpenDirectory(LPCSTR path);
+ static int CreateOrOpenFile(LPCSTR path, bool createIfNotExist = true, bool *createdRef = nullptr);
+ static void CloseFile(int fileDescriptor);
+
+ static SIZE_T GetFileSize(int fileDescriptor);
+ static void SetFileSize(int fileDescriptor, SIZE_T byteCount);
+
+ static void *MemoryMapFile(int fileDescriptor, SIZE_T byteCount);
+
+ static bool TryAcquireFileLock(int fileDescriptor, int operation);
+ static void ReleaseFileLock(int fileDescriptor);
+};
+
+class SharedMemoryId
+{
+private:
+ LPCSTR m_name;
+ SIZE_T m_nameCharCount;
+ bool m_isSessionScope; // false indicates global scope
+
+public:
+ SharedMemoryId();
+ SharedMemoryId(LPCSTR name, SIZE_T nameCharCount, bool isSessionScope);
+ SharedMemoryId(LPCSTR name);
+
+public:
+ LPCSTR GetName() const;
+ SIZE_T GetNameCharCount() const;
+ bool IsSessionScope() const;
+ bool Equals(SharedMemoryId *other) const;
+
+public:
+ SIZE_T AppendSessionDirectoryName(char (&path)[SHARED_MEMORY_MAX_FILE_PATH_CHAR_COUNT + 1], SIZE_T pathCharCount) const;
+};
+
+enum class SharedMemoryType : UINT8
+{
+ Mutex
+};
+
+class SharedMemorySharedDataHeader
+{
+private:
+ union
+ {
+ struct
+ {
+ SharedMemoryType m_type;
+ UINT8 m_version;
+ };
+ UINT64 _raw; // use the same size for the header on all archs, and align the data to a pointer
+ };
+
+public:
+ static SIZE_T DetermineTotalByteCount(SIZE_T dataByteCount);
+
+public:
+ SharedMemorySharedDataHeader(SharedMemoryType type, UINT8 version);
+
+public:
+ SharedMemoryType GetType() const;
+ UINT8 GetVersion() const;
+ void *GetData();
+};
+
+class SharedMemoryProcessDataBase
+{
+public:
+ virtual void Close(bool isAbruptShutdown, bool releaseSharedData)
+ {
+ }
+
+ virtual ~SharedMemoryProcessDataBase()
+ {
+ }
+};
+
+class SharedMemoryProcessDataHeader
+{
+private:
+ SIZE_T m_refCount;
+ SharedMemoryId m_id;
+ SharedMemoryProcessDataBase *m_data;
+ int m_fileDescriptor;
+ SharedMemorySharedDataHeader *m_sharedDataHeader;
+ SIZE_T m_sharedDataTotalByteCount;
+ SharedMemoryProcessDataHeader *m_nextInProcessDataHeaderList;
+
+public:
+ static SharedMemoryProcessDataHeader *CreateOrOpen(LPCSTR name, SharedMemorySharedDataHeader requiredSharedDataHeader, SIZE_T sharedDataByteCount, bool createIfNotExist, bool *createdRef);
+
+public:
+ static SharedMemoryProcessDataHeader *PalObject_GetProcessDataHeader(CorUnix::IPalObject *object);
+ static void PalObject_SetProcessDataHeader(CorUnix::IPalObject *object, SharedMemoryProcessDataHeader *processDataHeader);
+ static void PalObject_Close(CorUnix::CPalThread *thread, CorUnix::IPalObject *object, bool isShuttingDown, bool cleanUpPalSharedState);
+
+private:
+ SharedMemoryProcessDataHeader(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount);
+public:
+ static SharedMemoryProcessDataHeader *New(SharedMemoryId *id, int fileDescriptor, SharedMemorySharedDataHeader *sharedDataHeader, SIZE_T sharedDataTotalByteCount);
+ ~SharedMemoryProcessDataHeader();
+ void Close();
+
+public:
+ SharedMemoryId *GetId();
+ SharedMemoryProcessDataBase *GetData() const;
+ void SetData(SharedMemoryProcessDataBase *data);
+ SharedMemorySharedDataHeader *GetSharedDataHeader() const;
+ SIZE_T GetSharedDataTotalByteCount() const;
+ SharedMemoryProcessDataHeader *GetNextInProcessDataHeaderList() const;
+ void SetNextInProcessDataHeaderList(SharedMemoryProcessDataHeader *next);
+
+public:
+ void IncRefCount();
+ void DecRefCount();
+};
+
+class SharedMemoryManager
+{
+private:
+ static CRITICAL_SECTION s_creationDeletionProcessLock;
+ static int s_creationDeletionLockFileDescriptor;
+
+private:
+ static SharedMemoryProcessDataHeader *s_processDataHeaderListHead;
+
+#ifdef _DEBUG
+private:
+ static SIZE_T s_creationDeletionProcessLockOwnerThreadId;
+ static SIZE_T s_creationDeletionFileLockOwnerThreadId;
+#endif // _DEBUG
+
+public:
+ static void StaticInitialize();
+ static void StaticClose();
+
+public:
+ static void AcquireCreationDeletionProcessLock();
+ static void ReleaseCreationDeletionProcessLock();
+ static void AcquireCreationDeletionFileLock();
+ static void ReleaseCreationDeletionFileLock();
+
+#ifdef _DEBUG
+public:
+ static bool IsCreationDeletionProcessLockAcquired();
+ static bool IsCreationDeletionFileLockAcquired();
+#endif // _DEBUG
+
+public:
+ static void AddProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader);
+ static void RemoveProcessDataHeader(SharedMemoryProcessDataHeader *processDataHeader);
+ static SharedMemoryProcessDataHeader *FindProcessDataHeader(SharedMemoryId *id);
+};
+
+#endif // !_PAL_SHARED_MEMORY_H_
diff --git a/src/pal/src/include/pal/sharedmemory.inl b/src/pal/src/include/pal/sharedmemory.inl
new file mode 100644
index 0000000000..69b8704b65
--- /dev/null
+++ b/src/pal/src/include/pal/sharedmemory.inl
@@ -0,0 +1,53 @@
+// 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.
+
+#ifndef _PAL_SHARED_MEMORY_INL_
+#define _PAL_SHARED_MEMORY_INL_
+
+#include "sharedmemory.h"
+
+#include "dbgmsg.h"
+
+#include <string.h>
+
+template<SIZE_T DestinationByteCount, SIZE_T SourceByteCount>
+SIZE_T SharedMemoryHelpers::CopyString(
+ char (&destination)[DestinationByteCount],
+ SIZE_T destinationStartOffset,
+ const char(&source)[SourceByteCount])
+{
+ return CopyString(destination, destinationStartOffset, source, SourceByteCount - 1);
+}
+
+template<SIZE_T DestinationByteCount>
+SIZE_T SharedMemoryHelpers::CopyString(
+ char (&destination)[DestinationByteCount],
+ SIZE_T destinationStartOffset,
+ LPCSTR source,
+ SIZE_T sourceCharCount)
+{
+ _ASSERTE(destinationStartOffset < DestinationByteCount);
+ _ASSERTE(sourceCharCount < DestinationByteCount - destinationStartOffset);
+ _ASSERTE(strlen(source) == sourceCharCount);
+
+ memcpy_s(&destination[destinationStartOffset], DestinationByteCount - destinationStartOffset, source, sourceCharCount + 1);
+ return destinationStartOffset + sourceCharCount;
+}
+
+template<SIZE_T DestinationByteCount>
+SIZE_T SharedMemoryHelpers::AppendUInt32String(
+ char (&destination)[DestinationByteCount],
+ SIZE_T destinationStartOffset,
+ UINT32 value)
+{
+ _ASSERTE(destination != nullptr);
+ _ASSERTE(destinationStartOffset < DestinationByteCount);
+
+ int valueCharCount =
+ sprintf_s(&destination[destinationStartOffset], DestinationByteCount - destinationStartOffset, "%u", value);
+ _ASSERTE(valueCharCount > 0);
+ return destinationStartOffset + valueCharCount;
+}
+
+#endif // !_PAL_SHARED_MEMORY_INL_
diff --git a/src/pal/src/include/pal/shm.hpp b/src/pal/src/include/pal/shm.hpp
new file mode 100644
index 0000000000..de1d09e636
--- /dev/null
+++ b/src/pal/src/include/pal/shm.hpp
@@ -0,0 +1,83 @@
+// 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:
+
+ include/pal/shm.hpp
+
+Abstract:
+ C++ typesafe accessors for shared memory routines
+
+
+
+--*/
+
+#ifndef _SHM_HPP_
+#define _SHM_HPP_
+
+#include "shmemory.h"
+
+//
+// Some compilers (e.g., HPUX/IA64) warn about using NULL to initialize
+// something of type SHMPTR, since SHMPTR is defined as DWORD_PTR, which
+// isn't considered a pointer type...
+//
+
+#define SHMNULL 0
+
+#ifndef _DEBUG
+
+inline
+void *
+ShmPtrToPtrFast(SHMPTR shmptr)
+{
+ void *pv = NULL;
+
+ if (SHMNULL != shmptr)
+ {
+ int segment = shmptr >> 24;
+
+ if (segment < shm_numsegments)
+ {
+ pv = reinterpret_cast<void*>(
+ reinterpret_cast<DWORD_PTR>(shm_segment_bases[(uint)segment].Load())
+ + (shmptr & 0x00FFFFFF)
+ );
+ }
+ else
+ {
+ pv = SHMPtrToPtr(shmptr);
+ }
+ }
+
+ return pv;
+}
+
+//
+// We could use a function template here to avoid the cast / macro
+//
+
+#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast<type*>(ShmPtrToPtrFast((shmptr)))
+
+#else
+
+#define SHMPTR_TO_TYPED_PTR(type, shmptr) reinterpret_cast<type*>(SHMPtrToPtr((shmptr)))
+
+#endif
+
+/* Set ptr to NULL if shmPtr == 0, else set ptr to SHMPTR_TO_TYPED_PTR(type, shmptr)
+ return FALSE if SHMPTR_TO_TYPED_PTR returns NULL ptr from non null shmptr,
+ TRUE otherwise */
+#define SHMPTR_TO_TYPED_PTR_BOOL(type, ptr, shmptr) \
+ ((shmptr != 0) ? ((ptr = SHMPTR_TO_TYPED_PTR(type, shmptr)) != NULL) : ((ptr = NULL) == NULL))
+
+
+
+
+#endif // _SHM_HPP_
+
diff --git a/src/pal/src/include/pal/shmemory.h b/src/pal/src/include/pal/shmemory.h
new file mode 100644
index 0000000000..5ca848148c
--- /dev/null
+++ b/src/pal/src/include/pal/shmemory.h
@@ -0,0 +1,331 @@
+// 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:
+
+ include/pal/shmemory.h
+
+Abstract:
+ Header file for interface to shared memory
+
+How to use :
+
+The SHMalloc function can be used to allocate memory in the shared memory area.
+It returns a value of type SHMPTR, which will be useable in all participating
+processes. The SHMPTR_TO_PTR macro can be used to convert a SHMPTR value into
+an address valid *only* within the current process. Do NOT store pointers in
+shared memory, since those will not be valid for other processes. If you need
+to construct linked lists or other strctures that usually use pointers, use
+SHMPTR values instead of pointers. In addition, Lock/Release functions must be
+used when manipulating data in shared memory, to ensure inter-process synchronization.
+
+Example :
+
+//a simple linked list type
+typedef struct
+{
+int count;
+SHMPTR string;
+SHMPTR next;
+}SHMLIST;
+
+// Allocate a new list item
+SHMPTR new_item = SHMalloc(sizeof(SHMLIST));
+
+// get a pointer to it
+SHMLIST *item_ptr = (SHMLIST *)SHMPTR_TO_PTR(new_item);
+
+// Allocate memory for the "string" member, initialize it
+item_ptr->string = SHMalloc(strlen("string"));
+LPSTR str_ptr = (LPSTR)SHMPTR_TO_PTR(item_ptr->string);
+strcpy(str_ptr, "string");
+
+//Take the shared memory lock to prevent anyone from modifying the linked list
+SHMLock();
+
+//get the list's head from somewhere
+SHMPTR list_head = get_list_head();
+
+//link the list to our new item
+item_ptr->next = list_head
+
+//get a pointer to the list head's structure
+SHMLIST *head_ptr = (SHMLIST *)SHMPTR_TO_PTR(list_head);
+
+//set the new item's count value based on the head's count value
+item_ptr->count = head_ptr->count + 1;
+
+//save the new item as the new head of the list
+set_list_head(new_item);
+
+//We're done modifying the list, release the lock
+SHMRelease
+
+
+
+--*/
+
+#ifndef _PAL_SHMEMORY_H_
+#define _PAL_SHMEMORY_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*
+Type for shared memory blocks. use SHMPTR_TO_PTR to get a useable address.
+ */
+typedef DWORD_PTR SHMPTR;
+
+#define MAX_SEGMENTS 256
+
+
+typedef enum {
+ SIID_PROCESS_INFO,/* pointers to PROCESS structures? */
+ SIID_NAMED_OBJECTS,
+ SIID_FILE_LOCKS,
+
+ SIID_LAST
+} SHM_INFO_ID;
+
+typedef enum
+{
+ SHM_NAMED_MAPPINGS, /* structs with map name, file name & flags? */
+ SHM_NAMED_EVENTS, /* structs with event names & ThreadWaitingList struct? */
+ SHM_NAMED_MUTEXS, /* structs with mutext names, and ThreadWaitingList struct */
+
+ SHM_NAMED_LAST
+} SHM_NAMED_OBJECTS_ID;
+
+typedef struct _SMNO
+{
+ SHM_NAMED_OBJECTS_ID ObjectType;
+ SHMPTR ShmNext;
+ SHMPTR ShmObjectName;
+ SHMPTR ShmSelf;
+
+}SHM_NAMED_OBJECTS, * PSHM_NAMED_OBJECTS;
+
+
+/*
+SHMPTR_TO_PTR
+
+Macro to convert a SHMPTR value into a valid (for this process) pointer.
+
+In debug builds, we always call the function to do full checks.
+In release builds, check if the segment is known, and if it is, do only minimal
+validation (if segment is unknown, we have to call the function)
+ */
+#if _DEBUG
+
+#define SHMPTR_TO_PTR(shmptr) \
+ SHMPtrToPtr(shmptr)
+
+#else /* !_DEBUG */
+
+extern int shm_numsegments;
+
+/* array containing the base address of each segment */
+extern Volatile<LPVOID> shm_segment_bases[MAX_SEGMENTS];
+
+#define SHMPTR_TO_PTR(shmptr)\
+ ((shmptr)?(((static_cast<int>(shmptr)>>24)<shm_numsegments)?\
+ reinterpret_cast<LPVOID>(reinterpret_cast<size_t>(shm_segment_bases[static_cast<int>(shmptr)>>24].Load())+(static_cast<int>(shmptr)&0x00FFFFFF)):\
+ SHMPtrToPtr(shmptr)): static_cast<LPVOID>(NULL))
+
+
+#endif /* _DEBUG */
+
+/* Set ptr to NULL if shmPtr == 0, else set ptr to SHMPTR_TO_PTR(shmptr)
+ return FALSE if SHMPTR_TO_PTR returns NULL ptr from non null shmptr,
+ TRUE otherwise */
+#define SHMPTR_TO_PTR_BOOL(ptr, shmptr) \
+ ((shmptr != 0) ? ((ptr = SHMPTR_TO_PTR(shmptr)) != NULL) : ((ptr = NULL) == NULL))
+
+/*++
+SHMPtrToPtr
+
+Convert a SHMPTR value into a useable pointer.
+
+Unlike the macro defined above, this function performs as much validation as
+possible, and can handle cases when the SHMPTR is located in an aread of shared
+memory the process doesn't yet know about.
+--*/
+LPVOID SHMPtrToPtr(SHMPTR shmptr);
+
+/*++
+SHMInitialize
+
+Hook this process into the PAL shared memory system; initialize the shared
+memory if no other process has done it.
+--*/
+BOOL SHMInitialize(void);
+
+/*++
+SHMCleanup
+
+Release all shared memory resources held; remove ourselves from the list of
+registered processes, and remove all shared memory files if no process remains
+--*/
+void SHMCleanup(void);
+
+/*++
+SHMalloc
+
+Allocate a block of memory of the specified size
+
+Parameters :
+ size_t size : size of block required
+
+Return value :
+ A SHMPTR identifying the new block, or 0 on failure. Use SHMPtrToPtr to
+ convert a SHMPTR into a useable pointer (but remember to lock the shared
+ memory first!)
+
+Notes :
+ SHMalloc will fail if the requested size is larger than a certain maximum.
+ At the moment, the maximum is 520 bytes (MAX_PATH_FNAME*2).
+--*/
+SHMPTR SHMalloc(size_t size);
+
+/*++
+SHMfree
+
+Release a block of shared memory and put it back in the shared memory pool
+
+Parameters :
+ SHMPTR shmptr : identifier of block to release
+
+(no return value)
+--*/
+void SHMfree(SHMPTR shmptr);
+
+/*++
+SHMLock
+
+Restrict shared memory access to the current thread of the current process
+
+(no parameters)
+
+Return value :
+ New lock count
+--*/
+int SHMLock(void);
+
+/*++
+SHMRelease
+
+Release a lock on shared memory taken with SHMLock.
+
+(no parameters)
+
+Return value :
+ New lock count
+--*/
+int SHMRelease(void);
+
+
+/*++
+Function :
+ SHMGetInfo
+
+ Retrieve some information from shared memory
+
+Parameters :
+ SHM_INFO_ID element : identifier of element to retrieve
+
+Return value :
+ Value of specified element
+
+Notes :
+ The SHM lock should be held while manipulating shared memory
+--*/
+SHMPTR SHMGetInfo(SHM_INFO_ID element);
+
+/*++
+Function :
+ SHMSetInfo
+
+ Place some information into shared memory
+
+Parameters :
+ SHM_INFO_ID element : identifier of element to save
+ SHMPTR value : new value of element
+
+Return value :
+ TRUE if successfull, FALSE otherwise.
+
+Notes :
+ The SHM lock should be held while manipulating shared memory
+--*/
+BOOL SHMSetInfo(SHM_INFO_ID element, SHMPTR value);
+
+
+/********************** Shared memory help functions ********************/
+
+/*++
+SHMStrDup
+
+Duplicates the string in shared memory.
+
+Returns the new address as SHMPTR on success.
+Returns (SHMPTR)NULL on failure.
+--*/
+SHMPTR SHMStrDup( LPCSTR string );
+
+/*++
+SHMWStrDup
+
+Duplicates the wide string in shared memory.
+
+Returns the new address as SHMPTR on success.
+Returns (SHMPTR)NULL on failure.
+--*/
+SHMPTR SHMWStrDup( LPCWSTR string );
+
+
+/*++
+SHMFindNamedObjectByName
+
+Searches for an object whose name matches the name and ID passed in.
+
+Returns a SHMPTR to its location in shared memory. If no object
+matches the name, the function returns NULL and sets pbNameExists to FALSE.
+If an object matches the name but is of a different type, the function
+returns NULL and sets pbNameExists to TRUE.
+
+--*/
+SHMPTR SHMFindNamedObjectByName( LPCWSTR lpName, SHM_NAMED_OBJECTS_ID oid,
+ BOOL *pbNameExists );
+
+/*++
+SHMRemoveNamedObject
+
+Removes the specified named object from the list
+
+No return.
+
+note : the caller is reponsible for releasing all associated memory
+--*/
+void SHMRemoveNamedObject( SHMPTR shmNamedObject );
+
+/*++ SHMAddNamedObject
+
+Adds the specified named object to the list.
+
+No return.
+--*/
+void SHMAddNamedObject( SHMPTR shmNewNamedObject );
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_SHMEMORY_H_ */
+
diff --git a/src/pal/src/include/pal/stackstring.hpp b/src/pal/src/include/pal/stackstring.hpp
new file mode 100644
index 0000000000..1f18d5fe03
--- /dev/null
+++ b/src/pal/src/include/pal/stackstring.hpp
@@ -0,0 +1,239 @@
+// 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.
+
+#ifndef __STACKSTRING_H_
+#define __STACKSTRING_H_
+
+template <SIZE_T STACKCOUNT, class T>
+class StackString
+{
+private:
+ T m_innerBuffer[STACKCOUNT + 1];
+ T * m_buffer;
+ SIZE_T m_size; // actual allocated size
+ SIZE_T m_count; // actual length of string
+
+ void NullTerminate()
+ {
+ m_buffer[m_count] = 0;
+ }
+
+ void DeleteBuffer()
+ {
+ if (m_innerBuffer != m_buffer)
+ PAL_free(m_buffer);
+
+ m_buffer = NULL;
+ return;
+ }
+
+ BOOL ReallocateBuffer(SIZE_T count)
+ {
+ // count is always > STACKCOUNT here.
+ // We got so far, we will allocate a little extra
+ // to prevent frequent allocations
+#if _DEBUG
+ SIZE_T count_allocated = count;
+#else
+ SIZE_T count_allocated = count + 100;
+#endif //_DEBUG
+
+ BOOL dataOnStack = m_buffer == m_innerBuffer;
+ if( dataOnStack )
+ {
+ m_buffer = NULL;
+ }
+
+ T * newBuffer = (T *)PAL_realloc(m_buffer, (count_allocated + 1) * sizeof(T));
+ if (NULL == newBuffer)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+
+ DeleteBuffer();
+ m_count = 0;
+ m_buffer = m_innerBuffer;
+ return FALSE;
+ }
+
+ if( dataOnStack)
+ {
+ CopyMemory(newBuffer, m_innerBuffer, (m_count + 1) * sizeof(T));
+ }
+
+ m_buffer = newBuffer;
+ m_count = count;
+ m_size = count_allocated + 1;
+
+ return TRUE;
+ }
+
+ BOOL HasAvailableMemory(SIZE_T count)
+ {
+ return (count < m_size);
+ }
+
+ //NOTE: Always call this before modifying the underlying buffer
+ BOOL Resize(SIZE_T count)
+ {
+
+ if (NULL == m_buffer)
+ {
+ m_buffer = m_innerBuffer;
+ }
+
+ if (HasAvailableMemory(count))
+ {
+ m_count = count;
+ }
+ else
+ {
+ if (count > STACKCOUNT)
+ {
+ return ReallocateBuffer(count);
+ }
+ else
+ {
+ m_count = count;
+ m_size = STACKCOUNT+1;
+ }
+ }
+
+ return TRUE;
+ }
+
+ StackString(const StackString &s)
+ {
+ Set(s);
+ }
+
+public:
+ StackString()
+ : m_buffer(m_innerBuffer), m_size(0), m_count(0)
+ {
+ }
+
+
+ BOOL Set(const T * buffer, SIZE_T count)
+ {
+ if (!Resize(count))
+ return FALSE;
+
+ CopyMemory(m_buffer, buffer, (count + 1) * sizeof(T));
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL Set(const StackString &s)
+ {
+ return Set(s.m_buffer, s.m_count);
+ }
+
+ SIZE_T GetCount() const
+ {
+ return m_count;
+ }
+
+ SIZE_T GetSizeOf() const
+ {
+ return m_size * sizeof(T);
+ }
+
+ CONST T * GetString() const
+ {
+ return (const T *)m_buffer;
+ }
+
+ operator const T * () const { return GetString(); }
+
+ //Always preserves the existing content
+ T * OpenStringBuffer(SIZE_T count)
+ {
+ T * result = NULL;
+ if (Resize(count))
+ {
+ result = (T *)m_buffer;
+ }
+ return result;
+ }
+
+ //count should not include the terminating null
+ void CloseBuffer(SIZE_T count)
+ {
+ if (m_count > count)
+ m_count = count;
+
+ NullTerminate();
+ return;
+ }
+
+ //Call this with the best estimate if you want to
+ //prevent possible reallocations on further operations
+ BOOL Reserve(SIZE_T count)
+ {
+ SIZE_T endpos = m_count;
+
+ if (!Resize(count))
+ return FALSE;
+
+ m_count = endpos;
+ NullTerminate();
+
+ return TRUE;
+ }
+
+ //count Should not include the terminating null
+ BOOL Append(const T * buffer, SIZE_T count)
+ {
+ SIZE_T endpos = m_count;
+ if (!Resize(m_count + count))
+ return FALSE;
+
+ CopyMemory(&m_buffer[endpos], buffer, (count + 1) * sizeof(T));
+ NullTerminate();
+ return TRUE;
+ }
+
+ BOOL Append(const StackString &s)
+ {
+ return Append(s.GetString(), s.GetCount());
+ }
+
+ BOOL IsEmpty()
+ {
+ return 0 == m_buffer[0];
+ }
+
+ void Clear()
+ {
+ m_count = 0;
+ NullTerminate();
+ }
+ ~StackString()
+ {
+ DeleteBuffer();
+ }
+};
+
+#if _DEBUG
+typedef StackString<32, CHAR> PathCharString;
+typedef StackString<32, WCHAR> PathWCharString;
+#else
+typedef StackString<260, CHAR> PathCharString;
+typedef StackString<260, WCHAR> PathWCharString;
+#endif
+#endif
+
+// Some Helper Definitions
+BOOL
+PAL_GetPALDirectoryW(
+ PathWCharString& lpDirectoryName);
+BOOL
+PAL_GetPALDirectoryA(
+ PathCharString& lpDirectoryName);
+DWORD
+GetCurrentDirectoryA(
+ PathCharString& lpBuffer);
+void
+FILEDosToUnixPathA(
+ PathCharString& lpPath);
diff --git a/src/pal/src/include/pal/synchcache.hpp b/src/pal/src/include/pal/synchcache.hpp
new file mode 100644
index 0000000000..c172842292
--- /dev/null
+++ b/src/pal/src/include/pal/synchcache.hpp
@@ -0,0 +1,397 @@
+// 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:
+
+ include/pal/synchcache.hpp
+
+Abstract:
+ Simple look-aside cache for unused objects with default
+ constructor or no constructor
+
+
+
+--*/
+
+#ifndef _SYNCH_CACHE_H_
+#define _SYNCH_CACHE_H_
+
+#include "pal/thread.hpp"
+#include "pal/malloc.hpp"
+
+namespace CorUnix
+{
+ template <typename T> class CSynchCache
+ {
+ typedef union _USynchCacheStackNode
+ {
+ union _USynchCacheStackNode * next;
+ BYTE objraw[sizeof(T)];
+ } USynchCacheStackNode;
+
+ static const int MaxDepth = 256;
+
+ Volatile<USynchCacheStackNode*> m_pHead;
+ CRITICAL_SECTION m_cs;
+ Volatile<int> m_iDepth;
+ int m_iMaxDepth;
+#ifdef _DEBUG
+ int m_iMaxTrackedDepth;
+#endif
+
+ void Lock(CPalThread * pthrCurrent)
+ { InternalEnterCriticalSection(pthrCurrent, &m_cs); }
+ void Unlock(CPalThread * pthrCurrent)
+ { InternalLeaveCriticalSection(pthrCurrent, &m_cs); }
+
+ public:
+ CSynchCache(int iMaxDepth = MaxDepth) :
+ m_pHead(NULL),
+ m_iDepth(0),
+ m_iMaxDepth(iMaxDepth)
+#ifdef _DEBUG
+ ,m_iMaxTrackedDepth(0)
+#endif
+ {
+ InternalInitializeCriticalSection(&m_cs);
+ if (m_iMaxDepth < 0)
+ {
+ m_iMaxDepth = 0;
+ }
+ }
+
+ ~CSynchCache()
+ {
+ Flush(NULL, true);
+ InternalDeleteCriticalSection(&m_cs);
+ }
+
+#ifdef _DEBUG
+ int GetMaxTrackedDepth() { return m_iMaxTrackedDepth; }
+#endif
+
+ T * Get(CPalThread * pthrCurrent)
+ {
+ T * pObj = NULL;
+
+ Get(pthrCurrent, 1, &pObj);
+ return pObj;
+ }
+
+ int Get(CPalThread * pthrCurrent, int n, T ** ppObjs)
+ {
+ void * pvObjRaw;
+ USynchCacheStackNode * pNode;
+ int i = 0,j;
+
+ Lock(pthrCurrent);
+ pNode = m_pHead;
+ while (pNode && i < n)
+ {
+ ppObjs[i] = (T *)pNode;
+ pNode = pNode->next;
+ i++;
+ }
+ m_pHead = pNode;
+ m_iDepth -= i;
+
+#ifdef _DEBUG
+ if (NULL == m_pHead && m_iDepth != 0)
+ {
+ // Can't use ASSERT here, since this is header
+ // is included by other headers with inline methods
+ // which causes template instatiation in the header
+ // where the DEBUG CHANNEL is not defined and cannot
+ // be defined
+ fprintf(stderr,"SYNCCACHE: Invalid cache depth value");
+ DebugBreak();
+ }
+#endif // _DEBUG
+
+ Unlock(pthrCurrent);
+
+ for (j=i;j<n;j++)
+ {
+ pvObjRaw = (void *) InternalNew<USynchCacheStackNode>();
+ if (NULL == pvObjRaw)
+ break;
+#ifdef _DEBUG
+ memset(pvObjRaw, 0, sizeof(USynchCacheStackNode));
+#endif
+ ppObjs[j] = reinterpret_cast<T*>(pvObjRaw);
+ }
+
+ for (i=0;i<j;i++)
+ {
+ new ((void *)ppObjs[i]) T;
+ }
+
+ return j;
+ }
+
+ void Add(CPalThread * pthrCurrent, T * pobj)
+ {
+ USynchCacheStackNode * pNode = reinterpret_cast<USynchCacheStackNode *>(pobj);
+
+ if (NULL == pobj)
+ {
+ return;
+ }
+
+ pobj->~T();
+
+ Lock(pthrCurrent);
+ if (m_iDepth < m_iMaxDepth)
+ {
+#ifdef _DEBUG
+ if (m_iDepth > m_iMaxTrackedDepth)
+ {
+ m_iMaxTrackedDepth = m_iDepth;
+ }
+#endif
+ pNode->next = m_pHead;
+ m_pHead = pNode;
+ m_iDepth++;
+ }
+ else
+ {
+ InternalDelete((char *)pNode);
+ }
+ Unlock(pthrCurrent);
+ }
+
+ void Flush(CPalThread * pthrCurrent, bool fDontLock = false)
+ {
+ USynchCacheStackNode * pNode, * pTemp;
+
+ if (!fDontLock)
+ {
+ Lock(pthrCurrent);
+ }
+ pNode = m_pHead;
+ m_pHead = NULL;
+ m_iDepth = 0;
+ if (!fDontLock)
+ {
+ Unlock(pthrCurrent);
+ }
+
+ while (pNode)
+ {
+ pTemp = pNode;
+ pNode = pNode->next;
+ InternalDelete((char *)pTemp);
+ }
+ }
+ };
+
+ template <typename T> class CSHRSynchCache
+ {
+ union _USHRSynchCacheStackNode; // fwd declaration
+ typedef struct _SHRCachePTRs
+ {
+ union _USHRSynchCacheStackNode * pNext;
+ SharedID shrid;
+ } SHRCachePTRs;
+ typedef union _USHRSynchCacheStackNode
+ {
+ SHRCachePTRs pointers;
+ BYTE objraw[sizeof(T)];
+ } USHRSynchCacheStackNode;
+
+ static const int MaxDepth = 256;
+ static const int PreAllocFactor = 10; // Everytime a Get finds no available
+ // cached raw intances, it preallocates
+ // MaxDepth/PreAllocFactor new raw
+ // instances and store them into the
+ // cache before continuing
+
+ Volatile<USHRSynchCacheStackNode*> m_pHead;
+ CRITICAL_SECTION m_cs;
+ Volatile<int> m_iDepth;
+ int m_iMaxDepth;
+#ifdef _DEBUG
+ int m_iMaxTrackedDepth;
+#endif
+
+ void Lock(CPalThread * pthrCurrent)
+ { InternalEnterCriticalSection(pthrCurrent, &m_cs); }
+ void Unlock(CPalThread * pthrCurrent)
+ { InternalLeaveCriticalSection(pthrCurrent, &m_cs); }
+
+ public:
+ CSHRSynchCache(int iMaxDepth = MaxDepth) :
+ m_pHead(NULL),
+ m_iDepth(0),
+ m_iMaxDepth(iMaxDepth)
+#ifdef _DEBUG
+ ,m_iMaxTrackedDepth(0)
+#endif
+ {
+ InternalInitializeCriticalSection(&m_cs);
+ if (m_iMaxDepth < 0)
+ {
+ m_iMaxDepth = 0;
+ }
+ }
+
+ ~CSHRSynchCache()
+ {
+ Flush(NULL, true);
+ InternalDeleteCriticalSection(&m_cs);
+ }
+
+#ifdef _DEBUG
+ int GetMaxTrackedDepth() { return m_iMaxTrackedDepth; }
+#endif
+
+ SharedID Get(CPalThread * pthrCurrent)
+ {
+ SharedID shridObj = NULLSharedID;
+
+ Get(pthrCurrent, 1, &shridObj);
+ return shridObj;
+ }
+
+ int Get(CPalThread * pthrCurrent, int n, SharedID * shridpObjs)
+ {
+ SharedID shridObj;
+ void * pvObjRaw = NULL;
+ USHRSynchCacheStackNode * pNode;
+ int i = 0, j, k;
+
+ Lock(pthrCurrent);
+ pNode = m_pHead;
+ while (pNode && i < n)
+ {
+ shridpObjs[i] = pNode->pointers.shrid;
+ pvObjRaw = (void *)pNode;
+ pNode = pNode->pointers.pNext;
+ i++;
+ }
+ m_pHead = pNode;
+ m_iDepth -= i;
+
+#ifdef _DEBUG
+ if (NULL == m_pHead && m_iDepth != 0)
+ {
+ // Can't use ASSERT here, since this is header
+ // (see comment above)
+ fprintf(stderr,"SYNCCACHE: Invalid cache depth value");
+ DebugBreak();
+ }
+#endif // _DEBUG
+
+ if (0 == m_iDepth)
+ {
+ for (k=0; k<m_iMaxDepth/PreAllocFactor-n+i; k++)
+ {
+ shridObj = RawSharedObjectAlloc(sizeof(USHRSynchCacheStackNode), DefaultSharedPool);
+ if (NULLSharedID == shridObj)
+ {
+ Flush(pthrCurrent, true);
+ break;
+ }
+ pNode = SharedIDToTypePointer(USHRSynchCacheStackNode, shridObj);
+#ifdef _DEBUG
+ memset(reinterpret_cast<void*>(pNode), 0, sizeof(USHRSynchCacheStackNode));
+#endif
+ pNode->pointers.shrid = shridObj;
+ pNode->pointers.pNext = m_pHead;
+ m_pHead = pNode;
+ m_iDepth++;
+ }
+ }
+
+ Unlock(pthrCurrent);
+
+ for (j=i;j<n;j++)
+ {
+ shridObj = RawSharedObjectAlloc(sizeof(USHRSynchCacheStackNode), DefaultSharedPool);
+ if (NULLSharedID == shridObj)
+ break;
+#ifdef _DEBUG
+ pvObjRaw = SharedIDToPointer(shridObj);
+ memset(pvObjRaw, 0, sizeof(USHRSynchCacheStackNode));
+#endif
+ shridpObjs[j] = shridObj;
+ }
+
+ for (i=0;i<j;i++)
+ {
+ pvObjRaw = SharedIDToPointer(shridpObjs[i]);
+ new (pvObjRaw) T;
+ }
+
+ return j;
+ }
+
+ void Add(CPalThread * pthrCurrent, SharedID shridObj)
+ {
+ if (NULLSharedID == shridObj)
+ {
+ return;
+ }
+
+ USHRSynchCacheStackNode * pNode = SharedIDToTypePointer(USHRSynchCacheStackNode, shridObj);
+ T * pObj = reinterpret_cast<T *>(pNode);
+
+ pObj->~T();
+
+ pNode->pointers.shrid = shridObj;
+
+ Lock(pthrCurrent);
+ if (m_iDepth < m_iMaxDepth)
+ {
+ m_iDepth++;
+#ifdef _DEBUG
+ if (m_iDepth > m_iMaxTrackedDepth)
+ {
+ m_iMaxTrackedDepth = m_iDepth;
+ }
+#endif
+ pNode->pointers.pNext = m_pHead;
+ m_pHead = pNode;
+ }
+ else
+ {
+ RawSharedObjectFree(shridObj);
+ }
+ Unlock(pthrCurrent);
+ }
+
+ void Flush(CPalThread * pthrCurrent, bool fDontLock = false)
+ {
+ USHRSynchCacheStackNode * pNode, * pTemp;
+ SharedID shridTemp;
+
+ if (!fDontLock)
+ {
+ Lock(pthrCurrent);
+ }
+ pNode = m_pHead;
+ m_pHead = NULL;
+ m_iDepth = 0;
+ if (!fDontLock)
+ {
+ Unlock(pthrCurrent);
+ }
+
+ while (pNode)
+ {
+ pTemp = pNode;
+ pNode = pNode->pointers.pNext;
+ shridTemp = pTemp->pointers.shrid;
+ RawSharedObjectFree(shridTemp);
+ }
+ }
+ };
+}
+
+#endif // _SYNCH_CACHE_H_
+
diff --git a/src/pal/src/include/pal/synchobjects.hpp b/src/pal/src/include/pal/synchobjects.hpp
new file mode 100644
index 0000000000..aa3a8f1aa6
--- /dev/null
+++ b/src/pal/src/include/pal/synchobjects.hpp
@@ -0,0 +1,216 @@
+// 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:
+
+ include/pal/synchobjects.hpp
+
+Abstract:
+ Header file for synchronization manager and controllers
+
+
+
+--*/
+
+#ifndef _SINCHOBJECTS_HPP_
+#define _SINCHOBJECTS_HPP_
+
+#include "corunix.hpp"
+#include "threadinfo.hpp"
+#include "mutex.hpp"
+#include "shm.hpp"
+#include "list.h"
+
+#include <pthread.h>
+
+#define SharedID SHMPTR
+#define SharedPoolId ULONG_PTR
+#define DefaultSharedPool ((ULONG_PTR)0)
+#define NULLSharedID ((SHMPTR)NULL)
+#define SharedIDToPointer(shID) SHMPTR_TO_TYPED_PTR(PVOID, shID)
+#define SharedIDToTypePointer(TYPE,shID) SHMPTR_TO_TYPED_PTR(TYPE, shID)
+#define RawSharedObjectAlloc(szSize, shPoolId) SHMalloc(szSize)
+#define RawSharedObjectFree(shID) SHMfree(shID)
+
+namespace CorUnix
+{
+ DWORD InternalWaitForMultipleObjectsEx(
+ CPalThread * pthrCurrent,
+ DWORD nCount,
+ CONST HANDLE *lpHandles,
+ BOOL bWaitAll,
+ DWORD dwMilliseconds,
+ BOOL bAlertable);
+
+ PAL_ERROR InternalSleepEx(
+ CPalThread * pthrCurrent,
+ DWORD dwMilliseconds,
+ BOOL bAlertable);
+
+ enum THREAD_STATE
+ {
+ TS_IDLE,
+ TS_STARTING,
+ TS_RUNNING,
+ TS_FAILED,
+ TS_DONE,
+ };
+
+ // forward declarations
+ struct _ThreadWaitInfo;
+ struct _WaitingThreadsListNode;
+ class CSynchData;
+
+ typedef struct _WaitingThreadsListNode * PWaitingThreadsListNode;
+ typedef struct _OwnedObjectsListNode * POwnedObjectsListNode;
+ typedef struct _ThreadApcInfoNode * PThreadApcInfoNode;
+
+ typedef struct _ThreadWaitInfo
+ {
+ WaitType wtWaitType;
+ WaitDomain wdWaitDomain;
+ LONG lObjCount;
+ LONG lSharedObjCount;
+ CPalThread * pthrOwner;
+ PWaitingThreadsListNode rgpWTLNodes[MAXIMUM_WAIT_OBJECTS];
+
+ _ThreadWaitInfo() : wtWaitType(SingleObject), wdWaitDomain(LocalWait),
+ lObjCount(0), lSharedObjCount(0),
+ pthrOwner(NULL) {}
+ } ThreadWaitInfo;
+
+ typedef struct _ThreadNativeWaitData
+ {
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ int iPred;
+ DWORD dwObjectIndex;
+ ThreadWakeupReason twrWakeupReason;
+ bool fInitialized;
+
+ _ThreadNativeWaitData() :
+ iPred(0),
+ dwObjectIndex(0),
+ twrWakeupReason(WaitSucceeded),
+ fInitialized(false)
+ {
+ }
+
+ ~_ThreadNativeWaitData();
+ } ThreadNativeWaitData;
+
+ class CThreadSynchronizationInfo : public CThreadInfoInitializer
+ {
+ friend class CPalSynchronizationManager;
+ friend class CSynchWaitController;
+
+ THREAD_STATE m_tsThreadState;
+ SharedID m_shridWaitAwakened;
+ Volatile<LONG> m_lLocalSynchLockCount;
+ Volatile<LONG> m_lSharedSynchLockCount;
+ LIST_ENTRY m_leOwnedObjsList;
+
+ CRITICAL_SECTION m_ownedNamedMutexListLock;
+ NamedMutexProcessData *m_ownedNamedMutexListHead;
+
+ ThreadNativeWaitData m_tnwdNativeData;
+ ThreadWaitInfo m_twiWaitInfo;
+
+#ifdef SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING
+ static const int PendingSignalingsArraySize = 10;
+ LONG m_lPendingSignalingCount;
+ CPalThread * m_rgpthrPendingSignalings[PendingSignalingsArraySize];
+ LIST_ENTRY m_lePendingSignalingsOverflowList;
+#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING
+
+ public:
+
+ CThreadSynchronizationInfo();
+ virtual ~CThreadSynchronizationInfo();
+
+ //
+ // CThreadInfoInitializer methods
+ //
+ virtual PAL_ERROR InitializePreCreate(void);
+
+ virtual PAL_ERROR InitializePostCreate(
+ CPalThread *pthrCurrent,
+ SIZE_T threadId,
+ DWORD dwLwpId
+ );
+
+ THREAD_STATE GetThreadState(void)
+ {
+ return m_tsThreadState;
+ };
+
+ void SetThreadState(THREAD_STATE tsThreadState)
+ {
+ m_tsThreadState = tsThreadState;
+ };
+
+ ThreadNativeWaitData * GetNativeData()
+ {
+ return &m_tnwdNativeData;
+ }
+
+#if SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING
+ PAL_ERROR RunDeferredThreadConditionSignalings();
+#endif // SYNCHMGR_SUSPENSION_SAFE_CONDITION_SIGNALING
+
+ // NOTE: the following methods provide non-synchronized access to
+ // the list of owned objects for this thread. Any thread
+ // accessing this list MUST own the appropriate
+ // synchronization lock(s).
+ void AddObjectToOwnedList(POwnedObjectsListNode pooln);
+ void RemoveObjectFromOwnedList(POwnedObjectsListNode pooln);
+ POwnedObjectsListNode RemoveFirstObjectFromOwnedList(void);
+
+ void AddOwnedNamedMutex(NamedMutexProcessData *processData);
+ void RemoveOwnedNamedMutex(NamedMutexProcessData *processData);
+ NamedMutexProcessData *RemoveFirstOwnedNamedMutex();
+ bool OwnsNamedMutex(NamedMutexProcessData *processData);
+
+ // The following methods provide access to the native wait lock for
+ // those implementations that need a lock to protect the support for
+ // native thread blocking (e.g.: pthread conditions)
+ void AcquireNativeWaitLock(void);
+ void ReleaseNativeWaitLock(void);
+ bool TryAcquireNativeWaitLock(void);
+ };
+
+ class CThreadApcInfo : public CThreadInfoInitializer
+ {
+ friend class CPalSynchronizationManager;
+
+ PThreadApcInfoNode m_ptainHead;
+ PThreadApcInfoNode m_ptainTail;
+
+ public:
+ CThreadApcInfo() :
+ m_ptainHead(NULL),
+ m_ptainTail(NULL)
+ {
+ }
+ };
+
+ class CPalSynchMgrController
+ {
+ public:
+ static IPalSynchronizationManager * CreatePalSynchronizationManager();
+
+ static PAL_ERROR StartWorker(CPalThread * pthrCurrent);
+
+ static PAL_ERROR PrepareForShutdown(void);
+
+ static PAL_ERROR Shutdown(CPalThread *pthrCurrent, bool fFullCleanup);
+ };
+}
+
+#endif // _SINCHOBJECTS_HPP_
+
diff --git a/src/pal/src/include/pal/thread.hpp b/src/pal/src/include/pal/thread.hpp
new file mode 100644
index 0000000000..e6dacd2136
--- /dev/null
+++ b/src/pal/src/include/pal/thread.hpp
@@ -0,0 +1,838 @@
+// 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:
+
+ include/pal/thread.hpp
+
+Abstract:
+ Header file for thread structures
+
+
+
+--*/
+
+#ifndef _PAL_THREAD_HPP_
+#define _PAL_THREAD_HPP_
+
+#include "corunix.hpp"
+#include "shm.hpp"
+#include "cs.hpp"
+
+#include <pthread.h>
+#include <sys/syscall.h>
+#if HAVE_MACH_EXCEPTIONS
+#include <mach/mach.h>
+#endif // HAVE_MACH_EXCEPTIONS
+
+#include "threadsusp.hpp"
+#include "tls.hpp"
+#include "synchobjects.hpp"
+#include <errno.h>
+
+namespace CorUnix
+{
+ enum PalThreadType
+ {
+ UserCreatedThread,
+ PalWorkerThread,
+ SignalHandlerThread
+ };
+
+ PAL_ERROR
+ InternalCreateThread(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ DWORD dwStackSize,
+ LPTHREAD_START_ROUTINE lpStartAddress,
+ LPVOID lpParameter,
+ DWORD dwCreationFlags,
+ PalThreadType eThreadType,
+ LPDWORD lpThreadId,
+ HANDLE *phThread
+ );
+
+ PAL_ERROR
+ InternalGetThreadPriority(
+ CPalThread *pThread,
+ HANDLE hTargetThread,
+ int *piNewPriority
+ );
+
+ PAL_ERROR
+ InternalSetThreadPriority(
+ CPalThread *pThread,
+ HANDLE hTargetThread,
+ int iNewPriority
+ );
+
+ PAL_ERROR
+ InternalGetThreadDataFromHandle(
+ CPalThread *pThread,
+ HANDLE hThread,
+ DWORD dwRightsRequired,
+ CPalThread **ppTargetThread,
+ IPalObject **ppobjThread
+ );
+
+ VOID
+ InternalEndCurrentThread(
+ CPalThread *pThread
+ );
+
+ PAL_ERROR
+ InternalCreateDummyThread(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ CPalThread **ppDummyThread,
+ HANDLE *phThread
+ );
+
+ PAL_ERROR
+ InitializeGlobalThreadData(
+ void
+ );
+
+ PAL_ERROR
+ CreateThreadData(
+ CPalThread **ppThread
+ );
+
+ PAL_ERROR
+ CreateThreadObject(
+ CPalThread *pThread,
+ CPalThread *pNewThread,
+ HANDLE *phThread
+ );
+
+ PAL_ERROR
+ InitializeEndingThreadsData(
+ void
+ );
+
+ BOOL
+ GetThreadTimesInternal(
+ IN HANDLE hThread,
+ OUT LPFILETIME lpKernelTime,
+ OUT LPFILETIME lpUserTime);
+
+#ifdef FEATURE_PAL_SXS
+#if HAVE_MACH_EXCEPTIONS
+
+ // Structure used to return data about a single handler to a caller.
+ struct MachExceptionHandler
+ {
+ exception_mask_t m_mask;
+ exception_handler_t m_handler;
+ exception_behavior_t m_behavior;
+ thread_state_flavor_t m_flavor;
+ };
+
+ // Class abstracting previously registered Mach exception handlers for a thread.
+ struct CThreadMachExceptionHandlers
+ {
+ public:
+ // Maximum number of exception ports we hook. Must be the count
+ // of all bits set in the exception masks defined in machexception.h.
+ static const int s_nPortsMax = 6;
+
+ // Saved exception ports, exactly as returned by
+ // thread_swap_exception_ports.
+ mach_msg_type_number_t m_nPorts;
+ exception_mask_t m_masks[s_nPortsMax];
+ exception_handler_t m_handlers[s_nPortsMax];
+ exception_behavior_t m_behaviors[s_nPortsMax];
+ thread_state_flavor_t m_flavors[s_nPortsMax];
+
+ CThreadMachExceptionHandlers() :
+ m_nPorts(-1)
+ {
+ }
+
+ // Get handler details for a given type of exception. If successful the structure pointed at by
+ // pHandler is filled in and true is returned. Otherwise false is returned.
+ bool GetHandler(exception_type_t eException, MachExceptionHandler *pHandler);
+
+ private:
+ // Look for a handler for the given exception within the given handler node. Return its index if
+ // successful or -1 otherwise.
+ int GetIndexOfHandler(exception_mask_t bmExceptionMask);
+ };
+#endif // HAVE_MACH_EXCEPTIONS
+#endif // FEATURE_PAL_SXS
+
+ class CThreadSEHInfo : public CThreadInfoInitializer
+ {
+ public:
+#if !HAVE_MACH_EXCEPTIONS
+ BOOL safe_state;
+ int signal_code;
+#endif // !HAVE_MACH_EXCEPTIONSG
+
+ CThreadSEHInfo()
+ {
+ };
+ };
+
+ /* In the windows CRT there is a constant defined for the max width
+ of a _ecvt conversion. That constant is 348. 348 for the value, plus
+ the exponent value, decimal, and sign if required. */
+#define ECVT_MAX_COUNT_SIZE 348
+#define ECVT_MAX_BUFFER_SIZE 357
+
+ /*STR_TIME_SIZE is defined as 26 the size of the
+ return val by ctime_r*/
+#define STR_TIME_SIZE 26
+
+ class CThreadCRTInfo : public CThreadInfoInitializer
+ {
+ public:
+ CHAR * strtokContext; // Context for strtok function
+ WCHAR * wcstokContext; // Context for wcstok function
+ struct PAL_tm localtimeBuffer; // Buffer for localtime function
+ CHAR ctimeBuffer[ STR_TIME_SIZE ]; // Buffer for ctime function
+ CHAR ECVTBuffer[ ECVT_MAX_BUFFER_SIZE ]; // Buffer for _ecvt function.
+
+ CThreadCRTInfo() :
+ strtokContext(NULL),
+ wcstokContext(NULL)
+ {
+ ZeroMemory(&localtimeBuffer, sizeof(localtimeBuffer));
+ ZeroMemory(ctimeBuffer, sizeof(ctimeBuffer));
+ ZeroMemory(ECVTBuffer, sizeof(ECVTBuffer));
+ };
+ };
+
+ class CPalThread
+ {
+ friend
+ PAL_ERROR
+ CorUnix::InternalCreateThread(
+ CPalThread *,
+ LPSECURITY_ATTRIBUTES,
+ DWORD,
+ LPTHREAD_START_ROUTINE,
+ LPVOID,
+ DWORD,
+ PalThreadType,
+ LPDWORD,
+ HANDLE*
+ );
+
+ friend
+ PAL_ERROR
+ InternalCreateDummyThread(
+ CPalThread *pThread,
+ LPSECURITY_ATTRIBUTES lpThreadAttributes,
+ CPalThread **ppDummyThread,
+ HANDLE *phThread
+ );
+
+ friend
+ PAL_ERROR
+ InternalSetThreadPriority(
+ CPalThread *,
+ HANDLE,
+ int
+ );
+
+ friend
+ PAL_ERROR
+ InitializeGlobalThreadData(
+ void
+ );
+
+ friend
+ PAL_ERROR
+ CreateThreadData(
+ CPalThread **ppThread
+ );
+
+ friend
+ PAL_ERROR
+ CreateThreadObject(
+ CPalThread *pThread,
+ CPalThread *pNewThread,
+ HANDLE *phThread
+ );
+
+ friend CatchHardwareExceptionHolder;
+
+ private:
+
+ CPalThread *m_pNext;
+ DWORD m_dwExitCode;
+ BOOL m_fExitCodeSet;
+ CRITICAL_SECTION m_csLock;
+ bool m_fLockInitialized;
+ bool m_fIsDummy;
+
+ //
+ // Minimal reference count, used primarily for cleanup purposes. A
+ // new thread object has an initial refcount of 1. This initial
+ // reference is removed by CorUnix::InternalEndCurrentThread.
+ //
+ // The only other spot the refcount is touched is from within
+ // CPalObjectBase::ReleaseReference -- incremented before the
+ // destructors for an ojbect are called, and decremented afterwords.
+ // This permits the freeing of the thread structure to happen after
+ // the freeing of the enclosing thread object has completed.
+ //
+
+ LONG m_lRefCount;
+
+ //
+ // The IPalObject for this thread. The thread will release its reference
+ // to this object when it exits.
+ //
+
+ IPalObject *m_pThreadObject;
+
+ //
+ // Thread ID info
+ //
+
+ SIZE_T m_threadId;
+ DWORD m_dwLwpId;
+ pthread_t m_pthreadSelf;
+
+#if HAVE_MACH_THREADS
+ mach_port_t m_machPortSelf;
+#endif
+
+ // > 0 when there is an exception holder which causes h/w
+ // exceptions to be sent down the C++ exception chain.
+ int m_hardwareExceptionHolderCount;
+
+ //
+ // Start info
+ //
+
+ LPTHREAD_START_ROUTINE m_lpStartAddress;
+ LPVOID m_lpStartParameter;
+ BOOL m_bCreateSuspended;
+
+ int m_iThreadPriority;
+ PalThreadType m_eThreadType;
+
+ //
+ // pthread mutex / condition variable for gating thread startup.
+ // InternalCreateThread waits on the condition variable to determine
+ // when the new thread has reached passed all failure points in
+ // the entry routine
+ //
+
+ pthread_mutex_t m_startMutex;
+ pthread_cond_t m_startCond;
+ bool m_fStartItemsInitialized;
+ bool m_fStartStatus;
+ bool m_fStartStatusSet;
+
+ // Base address of the stack of this thread
+ void* m_stackBase;
+ // Limit address of the stack of this thread
+ void* m_stackLimit;
+
+ // The default stack size of a newly created thread (currently 256KB)
+ // when the dwStackSize paramter of PAL_CreateThread()
+ // is zero. This value can be set by setting the
+ // environment variable PAL_THREAD_DEFAULT_STACK_SIZE
+ // (the value should be in bytes and in hex).
+ static DWORD s_dwDefaultThreadStackSize;
+
+ //
+ // The thread entry routine (called from InternalCreateThread)
+ //
+
+ static void* ThreadEntry(void * pvParam);
+
+#ifdef FEATURE_PAL_SXS
+ //
+ // Data for PAL side-by-side support
+ //
+
+ private:
+ // This is set whenever this thread is currently executing within
+ // a region of code that depends on this instance of the PAL
+ // in the process.
+ bool m_fInPal;
+
+#if HAVE_MACH_EXCEPTIONS
+ // Record of Mach exception handlers that were already registered when we register our own CoreCLR
+ // specific handlers.
+ CThreadMachExceptionHandlers m_sMachExceptionHandlers;
+#endif // HAVE_MACH_EXCEPTIONS
+#endif // FEATURE_PAL_SXS
+
+ public:
+
+ //
+ // Embedded information for areas owned by other subsystems
+ //
+
+ CThreadSynchronizationInfo synchronizationInfo;
+ CThreadSuspensionInfo suspensionInfo;
+ CThreadSEHInfo sehInfo;
+ CThreadTLSInfo tlsInfo;
+ CThreadApcInfo apcInfo;
+ CThreadCRTInfo crtInfo;
+
+ CPalThread()
+ :
+ m_pNext(NULL),
+ m_dwExitCode(STILL_ACTIVE),
+ m_fExitCodeSet(FALSE),
+ m_fLockInitialized(FALSE),
+ m_fIsDummy(FALSE),
+ m_lRefCount(1),
+ m_pThreadObject(NULL),
+ m_threadId(0),
+ m_dwLwpId(0),
+ m_pthreadSelf(0),
+#if HAVE_MACH_THREADS
+ m_machPortSelf(0),
+#endif
+ m_hardwareExceptionHolderCount(0),
+ m_lpStartAddress(NULL),
+ m_lpStartParameter(NULL),
+ m_bCreateSuspended(FALSE),
+ m_iThreadPriority(THREAD_PRIORITY_NORMAL),
+ m_eThreadType(UserCreatedThread),
+ m_fStartItemsInitialized(FALSE),
+ m_fStartStatus(FALSE),
+ m_fStartStatusSet(FALSE),
+ m_stackBase(NULL),
+ m_stackLimit(NULL)
+#ifdef FEATURE_PAL_SXS
+ , m_fInPal(TRUE)
+#endif // FEATURE_PAL_SXS
+ {
+ };
+
+ virtual ~CPalThread();
+
+ PAL_ERROR
+ RunPreCreateInitializers(
+ void
+ );
+
+ //
+ // m_threadId and m_dwLwpId must be set before calling
+ // RunPostCreateInitializers
+ //
+
+ PAL_ERROR
+ RunPostCreateInitializers(
+ void
+ );
+
+ //
+ // SetStartStatus is called by THREADEntry or InternalSuspendNewThread
+ // to inform InternalCreateThread of the results of the thread's
+ // initialization. InternalCreateThread calls WaitForStartStatus to
+ // obtain this information (and will not return to its caller until
+ // the info is available).
+ //
+
+ void
+ SetStartStatus(
+ bool fStartSucceeded
+ );
+
+ bool
+ WaitForStartStatus(
+ void
+ );
+
+ void
+ Lock(
+ CPalThread *pThread
+ )
+ {
+ InternalEnterCriticalSection(pThread, &m_csLock);
+ };
+
+ void
+ Unlock(
+ CPalThread *pThread
+ )
+ {
+ InternalLeaveCriticalSection(pThread, &m_csLock);
+ };
+
+ //
+ // The following three methods provide access to the
+ // native lock used to protect thread native wait data.
+ //
+
+ void
+ AcquireNativeWaitLock(
+ void
+ )
+ {
+ synchronizationInfo.AcquireNativeWaitLock();
+ }
+
+ void
+ ReleaseNativeWaitLock(
+ void
+ )
+ {
+ synchronizationInfo.ReleaseNativeWaitLock();
+ }
+
+ bool
+ TryAcquireNativeWaitLock(
+ void
+ )
+ {
+ return synchronizationInfo.TryAcquireNativeWaitLock();
+ }
+
+ static void
+ SetLastError(
+ DWORD dwLastError
+ )
+ {
+ // Reuse errno to store last error
+ errno = dwLastError;
+ };
+
+ static DWORD
+ GetLastError(
+ void
+ )
+ {
+ // Reuse errno to store last error
+ return errno;
+ };
+
+ void
+ SetExitCode(
+ DWORD dwExitCode
+ )
+ {
+ m_dwExitCode = dwExitCode;
+ m_fExitCodeSet = TRUE;
+ };
+
+ BOOL
+ GetExitCode(
+ DWORD *pdwExitCode
+ )
+ {
+ *pdwExitCode = m_dwExitCode;
+ return m_fExitCodeSet;
+ };
+
+ SIZE_T
+ GetThreadId(
+ void
+ )
+ {
+ return m_threadId;
+ };
+
+ DWORD
+ GetLwpId(
+ void
+ )
+ {
+ return m_dwLwpId;
+ };
+
+ pthread_t
+ GetPThreadSelf(
+ void
+ )
+ {
+ return m_pthreadSelf;
+ };
+
+#if HAVE_MACH_THREADS
+ mach_port_t
+ GetMachPortSelf(
+ void
+ )
+ {
+ return m_machPortSelf;
+ };
+#endif
+
+ bool
+ IsHardwareExceptionsEnabled()
+ {
+ return m_hardwareExceptionHolderCount > 0;
+ }
+
+ LPTHREAD_START_ROUTINE
+ GetStartAddress(
+ void
+ )
+ {
+ return m_lpStartAddress;
+ };
+
+ LPVOID
+ GetStartParameter(
+ void
+ )
+ {
+ return m_lpStartParameter;
+ };
+
+ BOOL
+ GetCreateSuspended(
+ void
+ )
+ {
+ return m_bCreateSuspended;
+ };
+
+ PalThreadType
+ GetThreadType(
+ void
+ )
+ {
+ return m_eThreadType;
+ };
+
+ int
+ GetThreadPriority(
+ void
+ )
+ {
+ return m_iThreadPriority;
+ };
+
+ IPalObject *
+ GetThreadObject(
+ void
+ )
+ {
+ return m_pThreadObject;
+ }
+
+ BOOL
+ IsDummy(
+ void
+ )
+ {
+ return m_fIsDummy;
+ };
+
+ CPalThread*
+ GetNext(
+ void
+ )
+ {
+ return m_pNext;
+ };
+
+ void
+ SetNext(
+ CPalThread *pNext
+ )
+ {
+ m_pNext = pNext;
+ };
+
+ void
+ AddThreadReference(
+ void
+ );
+
+ void
+ ReleaseThreadReference(
+ void
+ );
+
+ // Get base address of the current thread's stack
+ static
+ void *
+ GetStackBase(
+ void
+ );
+
+ // Get cached base address of this thread's stack
+ // Can be called only for the current thread.
+ void *
+ GetCachedStackBase(
+ void
+ );
+
+ // Get limit address of the current thread's stack
+ static
+ void *
+ GetStackLimit(
+ void
+ );
+
+ // Get cached limit address of this thread's stack
+ // Can be called only for the current thread.
+ void *
+ GetCachedStackLimit(
+ void
+ );
+
+#ifdef FEATURE_PAL_SXS
+ //
+ // Functions for PAL side-by-side support
+ //
+
+ // This function needs to be called on a thread when it enters
+ // a region of code that depends on this instance of the PAL
+ // in the process.
+ PAL_ERROR Enter(PAL_Boundary boundary);
+
+ // This function needs to be called on a thread when it leaves
+ // a region of code that depends on this instance of the PAL
+ // in the process.
+ PAL_ERROR Leave(PAL_Boundary boundary);
+
+ // Returns TRUE whenever this thread is executing in a region
+ // of code that depends on this instance of the PAL in the process.
+ BOOL IsInPal()
+ {
+ return m_fInPal;
+ };
+
+#if HAVE_MACH_EXCEPTIONS
+ // Hook Mach exceptions, i.e., call thread_swap_exception_ports
+ // to replace the thread's current exception ports with our own.
+ // The previously active exception ports are saved. Called when
+ // this thread enters a region of code that depends on this PAL.
+ // Should only fail on internal errors.
+ PAL_ERROR EnableMachExceptions();
+
+ // Unhook Mach exceptions, i.e., call thread_set_exception_ports
+ // to restore the thread's exception ports with those we saved
+ // in EnableMachExceptions. Called when this thread leaves a
+ // region of code that depends on this PAL. Should only fail
+ // on internal errors.
+ PAL_ERROR DisableMachExceptions();
+
+ // The exception handling thread needs to be able to get at the list of handlers that installing our
+ // own handler on a thread has displaced (in case we need to forward an exception that we don't want
+ // to handle).
+ CThreadMachExceptionHandlers *GetSavedMachHandlers()
+ {
+ return &m_sMachExceptionHandlers;
+ }
+#endif // HAVE_MACH_EXCEPTIONS
+#endif // FEATURE_PAL_SXS
+ };
+
+#if defined(FEATURE_PAL_SXS)
+ extern "C" CPalThread *CreateCurrentThreadData();
+#endif // FEATURE_PAL_SXS
+
+ inline CPalThread *GetCurrentPalThread()
+ {
+ return reinterpret_cast<CPalThread*>(pthread_getspecific(thObjKey));
+ }
+
+ inline CPalThread *InternalGetCurrentThread()
+ {
+ CPalThread *pThread = GetCurrentPalThread();
+#if defined(FEATURE_PAL_SXS)
+ if (pThread == nullptr)
+ pThread = CreateCurrentThreadData();
+#endif // FEATURE_PAL_SXS
+ return pThread;
+ }
+
+/***
+
+ $$TODO: These are needed only to support cross-process thread duplication
+
+ class CThreadImmutableData
+ {
+ public:
+ DWORD dwProcessId;
+ };
+
+ class CThreadSharedData
+ {
+ public:
+ DWORD dwThreadId;
+ DWORD dwExitCode;
+ };
+***/
+
+ //
+ // The process local information for a thread is just a pointer
+ // to the underlying CPalThread object.
+ //
+
+ class CThreadProcessLocalData
+ {
+ public:
+ CPalThread *pThread;
+ };
+
+ extern CObjectType otThread;
+}
+
+BOOL
+TLSInitialize(
+ void
+ );
+
+VOID
+TLSCleanup(
+ void
+ );
+
+VOID
+WaitForEndingThreads(
+ void
+ );
+
+extern int free_threads_spinlock;
+
+extern PAL_ActivationFunction g_activationFunction;
+extern PAL_SafeActivationCheckFunction g_safeActivationCheckFunction;
+
+/*++
+Macro:
+ THREADSilentGetCurrentThreadId
+
+Abstract:
+ Same as GetCurrentThreadId, but it doesn't output any traces.
+ It is useful for tracing functions to display the thread ID
+ without generating any new traces.
+
+ TODO: how does the perf of pthread_self compare to
+ InternalGetCurrentThread when we find the thread in the
+ cache?
+
+ If the perf of pthread_self is comparable to that of the stack
+ bounds based lookaside system, why aren't we using it in the
+ cache?
+
+ In order to match the thread ids that debuggers use at least for
+ linux we need to use gettid().
+
+--*/
+#if defined(__linux__)
+#define THREADSilentGetCurrentThreadId() (SIZE_T)syscall(SYS_gettid)
+#elif defined(__APPLE__)
+inline SIZE_T THREADSilentGetCurrentThreadId() {
+ uint64_t tid;
+ pthread_threadid_np(pthread_self(), &tid);
+ return (SIZE_T)tid;
+}
+#elif defined(__NetBSD__)
+#include <lwp.h>
+#define THREADSilentGetCurrentThreadId() (SIZE_T)_lwp_self()
+#else
+#define THREADSilentGetCurrentThreadId() (SIZE_T)pthread_self()
+#endif
+
+#endif // _PAL_THREAD_HPP_
diff --git a/src/pal/src/include/pal/threadinfo.hpp b/src/pal/src/include/pal/threadinfo.hpp
new file mode 100644
index 0000000000..93ba0ababd
--- /dev/null
+++ b/src/pal/src/include/pal/threadinfo.hpp
@@ -0,0 +1,89 @@
+// 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:
+
+ include/pal/threadinfo.hpp
+
+Abstract:
+ Header file for thread info initialzer
+
+
+
+--*/
+
+#ifndef _PAL_THREADINFO_H_
+#define _PAL_THREADINFO_H_
+
+#include "corunix.hpp"
+
+namespace CorUnix
+{
+ //
+ // There are a number of different functional areas for which we need to
+ // store per-thread data:
+ // * synchronization
+ // * structure exception handling
+ // * asynchronous procedure calls
+ // * thread suspension
+ // * thread-local storage
+ // * CRT per-thread buffers
+ //
+ // For each of the above functional areas we build a class that stores
+ // the necessary data. An instance of each of these classes is embedded
+ // in the main thread class. The classes must not have any failure paths
+ // in their constructors. Each class inherits from a common parent class
+ // that exposes two virtual initialization routines (which may return an
+ // error). The first initialization routine is called after the thread
+ // object is allocated, but before the new thread is created. Any
+ // initialization that is not dependant on knowledge of the new thread's
+ // ID (and by extension need not run in the context of the new thread)
+ // should take place in the first routine. Work that must run in the
+ // context of the new thread or that must know the new thread's ID
+ // should take place in the second initialization routine.
+ //
+
+ class CThreadInfoInitializer
+ {
+ public:
+
+ //
+ // InitializePreCreate is called before the new thread is started.
+ // Any allocations or other initializations that may fail that do
+ // not need to run in the context of the new thread (or know the
+ // new thread's ID) should take place in this routine.
+ //
+
+ virtual
+ PAL_ERROR
+ InitializePreCreate(
+ void
+ )
+ {
+ return NO_ERROR;
+ };
+
+ //
+ // InitializePostCreate is called from within the context of the
+ // new thread.
+ //
+
+ virtual
+ PAL_ERROR
+ InitializePostCreate(
+ CPalThread *pThread,
+ SIZE_T threadId,
+ DWORD dwLwpId
+ )
+ {
+ return NO_ERROR;
+ };
+ };
+}
+
+#endif // _PAL_THREADINFO_H_
diff --git a/src/pal/src/include/pal/threadsusp.hpp b/src/pal/src/include/pal/threadsusp.hpp
new file mode 100644
index 0000000000..e1e85e265c
--- /dev/null
+++ b/src/pal/src/include/pal/threadsusp.hpp
@@ -0,0 +1,382 @@
+// 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:
+
+ include/pal/threadsusp.hpp
+
+Abstract:
+ Declarations for thread suspension
+
+
+
+--*/
+
+#ifndef _PAL_THREADSUSP_HPP
+#define _PAL_THREADSUSP_HPP
+
+// Need this ifdef since this header is included by .c files so they can use the diagnostic function.
+#ifdef __cplusplus
+
+// Note: do not include malloc.hpp from this header. The template InternalDelete
+// needs to know the layout of class CPalThread, which includes a member of type
+// CThreadSuspensionInfo, which is defined later in this header, and it is not
+// yet known at this point.
+// If any future change should bring this issue back, the circular dependency can
+// be further broken by making the InternalDelete's CPalThread argument a
+// templatized argument, so that type checking on it takes place only at
+// instantiation time.
+#include "pal/threadinfo.hpp"
+#include "pal/thread.hpp"
+#include "pal/printfcpp.hpp"
+#include "pal/mutex.hpp"
+#include "pal/init.h"
+#if !HAVE_MACH_EXCEPTIONS
+#include <signal.h>
+#endif // !HAVE_MACH_EXCEPTIONS
+#include <semaphore.h>
+#include <sched.h>
+
+// We have a variety of options for synchronizing thread suspensions and resumptions between the requestor and
+// target threads. Analyze the various capabilities given to us by configure and define one of three macros
+// here for simplicity:
+// USE_POSIX_SEMAPHORES
+// USE_SYSV_SEMAPHORES
+// USE_PTHREAD_CONDVARS
+#if HAS_POSIX_SEMAPHORES
+
+// Favor posix semaphores.
+#define USE_POSIX_SEMAPHORES 1
+
+#if HAVE_SYS_SEMAPHORE_H
+#include <sys/semaphore.h>
+#endif // HAVE_SYS_SEMAPHORE_H
+
+#elif HAS_PTHREAD_MUTEXES && HAVE_MACH_EXCEPTIONS
+
+// Can only use the pthread solution if we're not using signals since pthread mutexes are not signal safe.
+#define USE_PTHREAD_CONDVARS 1
+
+#include <pthread.h>
+
+#elif HAS_SYSV_SEMAPHORES
+
+// SYSV semaphores are our last choice since they're shared across processes so it's possible to leak them
+// on abnormal process termination.
+#define USE_SYSV_SEMAPHORES 1
+
+#include <sys/sem.h>
+#include <sys/types.h>
+
+#else
+#error "Don't know how to synchronize thread suspends and resumes on this platform"
+#endif // HAS_POSIX_SEMAPHORES
+
+#include <stdarg.h>
+
+namespace CorUnix
+{
+#ifdef _DEBUG
+#define MAX_TRACKED_CRITSECS 8
+#endif
+
+ PAL_ERROR
+ InternalResumeThread(
+ CPalThread *pthrResumer,
+ HANDLE hTarget,
+ DWORD *pdwSuspendCount
+ );
+
+ class CThreadSuspensionInfo : public CThreadInfoInitializer
+ {
+ private:
+ BOOL m_fPending; // TRUE if a suspension is pending on a thread (because the thread is in an unsafe region)
+ BOOL m_fSelfsusp; // TRUE if thread is self suspending and while thread is self suspended
+ BOOL m_fSuspendedForShutdown; // TRUE once the thread is suspended during PAL cleanup
+ int m_nBlockingPipe; // blocking pipe used for a process that was created suspended
+#ifdef _DEBUG
+ Volatile<LONG> m_lNumThreadsSuspendedByThisThread; // number of threads that this thread has suspended; used for suspension diagnostics
+#endif
+#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+ int m_nSpinlock; // thread's suspension spinlock, which is used to synchronize suspension and resumption attempts
+#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+ pthread_mutex_t m_ptmSuspmutex; // thread's suspension mutex, which is used to synchronize suspension and resumption attempts
+ BOOL m_fSuspmutexInitialized;
+#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+#if USE_POSIX_SEMAPHORES
+ sem_t m_semSusp; // suspension semaphore
+ sem_t m_semResume; // resumption semaphore
+ BOOL m_fSemaphoresInitialized;
+#elif USE_SYSV_SEMAPHORES
+ // necessary id's and sembuf structures for SysV semaphores
+ int m_nSemsuspid; // id for the suspend semaphore
+ int m_nSemrespid; // id for the resume semaphore
+ struct sembuf m_sbSemwait; // struct representing a wait operation
+ struct sembuf m_sbSempost; // struct representing a post operation
+#elif USE_PTHREAD_CONDVARS
+ pthread_cond_t m_condSusp; // suspension condition variable
+ pthread_mutex_t m_mutexSusp; // mutex associated with the condition above
+ BOOL m_fSuspended; // set to true once the suspend has been acknowledged
+
+ pthread_cond_t m_condResume; // resumption condition variable
+ pthread_mutex_t m_mutexResume; // mutex associated with the condition above
+ BOOL m_fResumed; // set to true once the resume has been acknowledged
+
+ BOOL m_fSemaphoresInitialized;
+#endif // USE_POSIX_SEMAPHORES
+
+ /* Most of the variables above are either accessed by a thread
+ holding the appropriate suspension mutex(es) or are only
+ accessed by their own threads (and thus don't require
+ synchronization).
+
+ m_fPending, m_fSuspendedForShutdown,
+ m_fSuspendSignalSent, and m_fResumeSignalSent
+ may be set by a different thread than the owner and thus
+ require synchronization.
+
+ m_fSelfsusp is set to TRUE only by its own thread but may be later
+ accessed by other threads.
+
+ m_lNumThreadsSuspendedByThisThread is accessed by its owning
+ thread and therefore does not require synchronization. */
+
+#ifdef _DEBUG
+ VOID
+ IncrNumThreadsSuspendedByThisThread(
+ )
+ {
+ InterlockedIncrement(&m_lNumThreadsSuspendedByThisThread);
+ };
+
+ VOID
+ DecrNumThreadsSuspendedByThisThread(
+ )
+ {
+ InterlockedDecrement(&m_lNumThreadsSuspendedByThisThread);
+ };
+#endif
+
+ VOID
+ AcquireSuspensionLocks(
+ CPalThread *pthrSuspender,
+ CPalThread *pthrTarget
+ );
+
+ VOID
+ ReleaseSuspensionLocks(
+ CPalThread *pthrSuspender,
+ CPalThread *pthrTarget
+ );
+
+#if USE_POSIX_SEMAPHORES
+ sem_t*
+ GetSuspendSemaphore(
+ void
+ )
+ {
+ return &m_semSusp;
+ };
+
+ sem_t*
+ GetResumeSemaphore(
+ void
+ )
+ {
+ return &m_semResume;
+ };
+#elif USE_SYSV_SEMAPHORES
+ int
+ GetSuspendSemaphoreId(
+ void
+ )
+ {
+ return m_nSemsuspid;
+ };
+
+ sembuf*
+ GetSemaphorePostBuffer(
+ void
+ )
+ {
+ return &m_sbSempost;
+ };
+#endif // USE_POSIX_SEMAPHORES
+
+#if DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+ LONG*
+ GetSuspensionSpinlock(
+ void
+ )
+ {
+ return &m_nSpinlock;
+ }
+#else // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+ pthread_mutex_t*
+ GetSuspensionMutex(
+ void
+ )
+ {
+ return &m_ptmSuspmutex;
+ }
+#endif // DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+
+ void
+ SetSuspPending(
+ BOOL fPending
+ )
+ {
+ m_fPending = fPending;
+ };
+
+ BOOL
+ GetSuspPending(
+ void
+ )
+ {
+ return m_fPending;
+ };
+
+ void
+ SetSelfSusp(
+ BOOL fSelfsusp
+ )
+ {
+ m_fSelfsusp = fSelfsusp;
+ };
+
+ BOOL
+ GetSelfSusp(
+ void
+ )
+ {
+ return m_fSelfsusp;
+ };
+
+ void
+ PostOnSuspendSemaphore();
+
+ void
+ WaitOnSuspendSemaphore();
+
+ void
+ PostOnResumeSemaphore();
+
+ void
+ WaitOnResumeSemaphore();
+
+ static
+ BOOL
+ TryAcquireSuspensionLock(
+ CPalThread* pthrTarget
+ );
+
+ int GetBlockingPipe(
+ void
+ )
+ {
+ return m_nBlockingPipe;
+ };
+
+ public:
+ virtual PAL_ERROR InitializePreCreate();
+
+ CThreadSuspensionInfo()
+ : m_fPending(FALSE)
+ , m_fSelfsusp(FALSE)
+ , m_fSuspendedForShutdown(FALSE)
+ , m_nBlockingPipe(-1)
+#ifdef _DEBUG
+ , m_lNumThreadsSuspendedByThisThread(0)
+#endif // _DEBUG
+#if !DEADLOCK_WHEN_THREAD_IS_SUSPENDED_WHILE_BLOCKED_ON_MUTEX
+ , m_fSuspmutexInitialized(FALSE)
+#endif
+#if USE_POSIX_SEMAPHORES || USE_PTHREAD_CONDVARS
+ , m_fSemaphoresInitialized(FALSE)
+#endif
+ {
+ InitializeSuspensionLock();
+ };
+
+ virtual ~CThreadSuspensionInfo();
+
+#ifdef _DEBUG
+ LONG
+ GetNumThreadsSuspendedByThisThread(
+ void
+ )
+ {
+ return m_lNumThreadsSuspendedByThisThread;
+ };
+#endif // _DEBUG
+
+#if USE_SYSV_SEMAPHORES
+ void
+ DestroySemaphoreIds(
+ void
+ );
+#endif
+ void
+ SetSuspendedForShutdown(
+ BOOL fSuspendedForShutdown
+ )
+ {
+ m_fSuspendedForShutdown = fSuspendedForShutdown;
+ };
+
+ BOOL
+ GetSuspendedForShutdown(
+ void
+ )
+ {
+ return m_fSuspendedForShutdown;
+ };
+
+ void
+ AcquireSuspensionLock(
+ CPalThread *pthrCurrent
+ );
+
+ void
+ ReleaseSuspensionLock(
+ CPalThread *pthrCurrent
+ );
+
+ PAL_ERROR
+ InternalSuspendNewThreadFromData(
+ CPalThread *pThread
+ );
+
+ PAL_ERROR
+ InternalResumeThreadFromData(
+ CPalThread *pthrResumer,
+ CPalThread *pthrTarget,
+ DWORD *pdwSuspendCount
+ );
+
+ VOID InitializeSuspensionLock();
+
+ void SetBlockingPipe(
+ int nBlockingPipe
+ )
+ {
+ m_nBlockingPipe = nBlockingPipe;
+ };
+ };
+} //end CorUnix
+
+extern const BYTE WAKEUPCODE; // use for pipe reads during self suspend.
+#endif // __cplusplus
+
+#ifdef USE_GLOBAL_LOCK_FOR_SUSPENSION
+extern LONG g_ssSuspensionLock;
+#endif
+
+#endif // _PAL_THREADSUSP_HPP
+
diff --git a/src/pal/src/include/pal/tls.hpp b/src/pal/src/include/pal/tls.hpp
new file mode 100644
index 0000000000..a4d9926c49
--- /dev/null
+++ b/src/pal/src/include/pal/tls.hpp
@@ -0,0 +1,65 @@
+// 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:
+
+ include/pal/tls.hpp
+
+Abstract:
+ Header file for thread local storage
+
+
+
+--*/
+
+#ifndef _PAL_TLS_HPP
+#define _PAL_TLS_HPP
+
+#include "threadinfo.hpp"
+
+namespace CorUnix
+{
+ /* This is the number of slots available for use in TlsAlloc().
+ sTlsSlotFields in thread/localstorage.c must be this number
+ of bits. */
+#define TLS_SLOT_SIZE 64
+
+ class CThreadTLSInfo : public CThreadInfoInitializer
+ {
+ public:
+ LPVOID tlsSlots[TLS_SLOT_SIZE];
+
+ virtual
+ PAL_ERROR
+ InitializePostCreate(
+ CPalThread *pThread,
+ SIZE_T threadId,
+ DWORD dwLwpId
+ );
+
+ CThreadTLSInfo()
+ {
+ ZeroMemory(tlsSlots, sizeof(tlsSlots));
+ };
+ };
+
+ //
+ // InternalGetCurrentThread obtains the CPalThread instance for the
+ // calling thread. That instance should only be used by the calling
+ // thread. If another thread will at some point need access to this
+ // thread information it should be given a referenced pointer to
+ // the IPalObject stored within the CPalThread.
+ //
+
+ extern pthread_key_t thObjKey;
+
+ CPalThread *InternalGetCurrentThread();
+}
+
+#endif // _PAL_TLS_HPP
+
diff --git a/src/pal/src/include/pal/unicode_data.h b/src/pal/src/include/pal/unicode_data.h
new file mode 100644
index 0000000000..0b7fe07447
--- /dev/null
+++ b/src/pal/src/include/pal/unicode_data.h
@@ -0,0 +1,69 @@
+// 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:
+
+ include/pal/unicode_data.h
+
+Abstract:
+
+ Data, data retrieval function declarations.
+
+
+
+--*/
+
+#ifndef _UNICODE_DATA_H_
+#define _UNICODE_DATA_H_
+
+#include "pal/palinternal.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+#if !HAVE_COREFOUNDATION
+
+typedef struct
+{
+ WCHAR nUnicodeValue;
+ WORD C1_TYPE_FLAGS;
+ WCHAR nOpposingCase; /* 0 if no opposing case. */
+ WORD rangeValue;
+} UnicodeDataRec;
+
+/* Global variables. */
+extern CONST UnicodeDataRec UnicodeData[];
+extern CONST UINT UNICODE_DATA_SIZE;
+extern CONST UINT UNICODE_DATA_DIRECT_ACCESS;
+
+/*++
+Function:
+ GetUnicodeData
+ This function is used to get information about a Unicode character.
+
+Parameters:
+nUnicodeValue
+ The numeric value of the Unicode character to get information about.
+pDataRec
+ The UnicodeDataRec to fill in with the data for the Unicode character.
+
+Return value:
+ TRUE if the Unicode character was found.
+
+--*/
+BOOL GetUnicodeData(INT nUnicodeValue, UnicodeDataRec *pDataRec);
+
+#endif /* !HAVE_COREFOUNDATION */
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _UNICODE_DATA_H_ */
diff --git a/src/pal/src/include/pal/utf8.h b/src/pal/src/include/pal/utf8.h
new file mode 100644
index 0000000000..2516caafb0
--- /dev/null
+++ b/src/pal/src/include/pal/utf8.h
@@ -0,0 +1,53 @@
+// 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:
+
+ include/pal/utf8.h
+
+Abstract:
+ Header file for UTF-8 conversion functions.
+
+Revision History:
+
+
+
+--*/
+
+#ifndef _PAL_UTF8_H_
+#define _PAL_UTF8_H_
+
+#include <pal/palinternal.h> /* for WCHAR */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function :
+ UTF8ToUnicode
+
+ Convert a string from UTF-8 to UTF-16 (UCS-2)
+--*/
+int UTF8ToUnicode(LPCSTR lpSrcStr, int cchSrc, LPWSTR lpDestStr, int cchDest, DWORD dwFlags);
+
+
+/*++
+Function :
+ UnicodeToUTF8
+
+ Convert a string from UTF-16 (UCS-2) to UTF-8
+--*/
+int UnicodeToUTF8(LPCWSTR lpSrcStr, int cchSrc, LPSTR lpDestStr, int cchDest);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* _PAL_UTF8_H_ */
diff --git a/src/pal/src/include/pal/utils.h b/src/pal/src/include/pal/utils.h
new file mode 100644
index 0000000000..3ddad4ae2f
--- /dev/null
+++ b/src/pal/src/include/pal/utils.h
@@ -0,0 +1,157 @@
+// 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:
+
+ include/pal/utils.h
+
+Abstract:
+ Miscellaneous helper functions for the PAL, which don't fit anywhere else
+
+
+
+--*/
+
+#ifndef _PAL_UTILS_H_
+#define _PAL_UTILS_H_
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+/*++
+Function:
+ UTIL_inverse_wcspbrk
+
+ Opposite of wcspbrk : searches a string for the first character NOT in the
+ given set
+
+Parameters :
+ LPWSTR lpwstr : string to search
+ LPCWSTR charset : list of characters to search for
+
+Return value :
+ pointer to first character of lpwstr that isn't in the set
+ NULL if all characters are in the set
+--*/
+LPWSTR UTIL_inverse_wcspbrk(LPWSTR lpwstr, LPCWSTR charset);
+
+/*++
+Function :
+ UTIL_IsReadOnlyBitsSet
+
+ Takes a struct stat *
+ Returns true if the file is read only,
+--*/
+BOOL UTIL_IsReadOnlyBitsSet( struct stat * stat_data );
+
+/*++
+Function :
+ UTIL_IsExecuteBitsSet
+
+ Takes a struct stat *
+ Returns true if the file is executable.
+--*/
+BOOL UTIL_IsExecuteBitsSet( struct stat * stat_data );
+
+
+/*++
+Function :
+ UTIL_WCToMB_Alloc
+
+ Converts a wide string to a multibyte string, allocating the required buffer
+
+Parameters :
+ LPCWSTR lpWideCharStr : string to convert
+ int cchWideChar : number of wide characters to convert
+ (-1 to convert a complete null-termnated string)
+
+Return Value :
+ newly allocated buffer containing the converted string. Conversion is
+ performed using CP_ACP. Buffer is allocated with malloc(), release it
+ with free().
+ In case if failure, LastError will be set.
+--*/
+LPSTR UTIL_WCToMB_Alloc(LPCWSTR lpWideCharStr, int cchWideChar);
+
+/*++
+Function :
+ UTIL_MBToWC_Alloc
+
+ Converts a multibyte string to a wide string, allocating the required buffer
+
+Parameters :
+ LPCSTR lpMultiByteStr : string to convert
+ int cbMultiByte : number of bytes to convert
+ (-1 to convert a complete null-termnated string)
+
+Return Value :
+ newly allocated buffer containing the converted string. Conversion is
+ performed using CP_ACP. Buffer is allocated with malloc(), release it
+ with free().
+ In case if failure, LastError will be set.
+--*/
+LPWSTR UTIL_MBToWC_Alloc(LPCSTR lpMultiByteStr, int cbMultiByte);
+
+#if HAVE_VM_ALLOCATE
+#include <mach/kern_return.h>
+
+/*++
+Function:
+ UTIL_MachErrorToPalError
+
+ Maps a Mach kern_return_t to a Win32 error code.
+--*/
+DWORD UTIL_MachErrorToPalError(kern_return_t MachReturn);
+
+/*++
+Function:
+ UTIL_SetLastErrorFromMach
+
+ Sets Win32 LastError according to the argument Mach kern_return_t value,
+ provided it indicates an error. If the argument indicates success, does
+ not modify LastError.
+--*/
+void UTIL_SetLastErrorFromMach(kern_return_t MachReturn);
+
+#endif //HAVE_VM_ALLOCATE
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+class StringHolder
+ {
+ private:
+ LPSTR data;
+ public:
+ StringHolder() : data(NULL) { }
+ ~StringHolder()
+ {
+ PAL_free( data);
+ }
+
+ operator LPSTR () { return data;}
+
+ StringHolder& operator= (LPSTR value)
+ {
+ data = value;
+ return *this;
+ }
+
+ BOOL IsNull()
+ {
+ return data == NULL;
+ }
+
+ };
+#endif /* _PAL_UTILS_H_ */
diff --git a/src/pal/src/include/pal/virtual.h b/src/pal/src/include/pal/virtual.h
new file mode 100644
index 0000000000..a4e225281e
--- /dev/null
+++ b/src/pal/src/include/pal/virtual.h
@@ -0,0 +1,208 @@
+// 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:
+
+ include/pal/virtual.h
+
+Abstract:
+ Header file for virtual memory management.
+
+
+
+--*/
+
+#ifndef _PAL_VIRTUAL_H_
+#define _PAL_VIRTUAL_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif // __cplusplus
+
+typedef struct _CMI {
+
+ struct _CMI * pNext; /* Link to the next entry. */
+ struct _CMI * pPrevious; /* Link to the previous entry. */
+
+ UINT_PTR startBoundary; /* Starting location of the region. */
+ SIZE_T memSize; /* Size of the entire region.. */
+
+ DWORD accessProtection; /* Initial allocation access protection. */
+ DWORD allocationType; /* Initial allocation type. */
+
+ BYTE * pAllocState; /* Individual allocation type tracking for each */
+ /* page in the region. */
+
+ BYTE * pProtectionState; /* Individual allocation type tracking for each */
+ /* page in the region. */
+
+} CMI, * PCMI;
+
+enum VIRTUAL_CONSTANTS
+{
+ /* Allocation type. */
+ VIRTUAL_COMMIT_ALL_BITS = 0xFF,
+ VIRTUAL_RESERVE_ALL_BITS = 0x0,
+
+ /* Protection Type. */
+ VIRTUAL_READONLY,
+ VIRTUAL_READWRITE,
+ VIRTUAL_EXECUTE_READWRITE,
+ VIRTUAL_NOACCESS,
+ VIRTUAL_EXECUTE,
+ VIRTUAL_EXECUTE_READ,
+
+ /* Page manipulation constants. */
+#ifdef __sparc__
+ VIRTUAL_PAGE_SIZE = 0x2000,
+#else // __sparc__
+ VIRTUAL_PAGE_SIZE = 0x1000,
+#endif // __sparc__
+ VIRTUAL_PAGE_MASK = VIRTUAL_PAGE_SIZE - 1,
+ BOUNDARY_64K = 0xffff
+};
+
+/*++
+Function :
+ VIRTUALInitialize
+
+ Initialize the critical sections.
+
+Return value:
+ TRUE if initialization succeeded
+ FALSE otherwise.
+--*/
+BOOL VIRTUALInitialize(bool initializeExecutableMemoryAllocator);
+
+/*++
+Function :
+ VIRTUALCleanup
+
+ Deletes the critical sections.
+
+--*/
+void VIRTUALCleanup( void );
+
+#ifdef __cplusplus
+}
+
+/*++
+Class:
+ ExecutableMemoryAllocator
+
+ This class implements a virtual memory allocator for JIT'ed code.
+ The purpose of this allocator is to opportunistically reserve a chunk of virtual memory
+ that is located near the coreclr library (within 2GB range) that can be later used by
+ JIT. Having executable memory close to the coreclr library allows JIT to generate more
+ efficient code (by avoiding usage of jump stubs) and thus it can significantly improve
+ performance of the application.
+
+ This allocator is integrated with the VirtualAlloc/Reserve code. If VirtualAlloc has been
+ called with the MEM_RESERVE_EXECUTABLE flag then it will first try to obtain the requested size
+ of virtual memory from ExecutableMemoryAllocator. If ExecutableMemoryAllocator runs out of
+ the reserved memory (or fails to allocate it during initialization) then VirtualAlloc/Reserve code
+ will simply fall back to reserving memory using OS APIs.
+
+ Notes:
+ - the memory allocated by this class is NOT committed by default. It is responsibility
+ of the caller to commit the virtual memory before accessing it.
+ - in addition, this class does not provide ability to free the reserved memory. The caller
+ has full control of the memory it got from this allocator (i.e. the caller becomes
+ the owner of the allocated memory), so it is caller's responsibility to free the memory
+ if it is no longer needed.
+--*/
+class ExecutableMemoryAllocator
+{
+public:
+ /*++
+ Function:
+ Initialize
+
+ This function initializes the allocator. It should be called early during process startup
+ (when process address space is pretty much empty) in order to have a chance to reserve
+ sufficient amount of memory that is close to the coreclr library.
+ --*/
+ void Initialize();
+
+ /*++
+ Function:
+ AllocateMemory
+
+ This function attempts to allocate the requested amount of memory from its reserved virtual
+ address space. The function will return NULL if the allocation request cannot
+ be satisfied by the memory that is currently available in the allocator.
+ --*/
+ void* AllocateMemory(SIZE_T allocationSize);
+
+private:
+ /*++
+ Function:
+ TryReserveInitialMemory
+
+ This function is called during initialization. It opportunistically tries to reserve
+ a large chunk of virtual memory that can be later used to store JIT'ed code.
+ --*/
+ void TryReserveInitialMemory();
+
+ /*++
+ Function:
+ GenerateRandomStartOffset
+
+ This function returns a random offset (in multiples of the virtual page size)
+ at which the allocator should start allocating memory from its reserved memory range.
+ --*/
+ int32_t GenerateRandomStartOffset();
+
+private:
+ // There does not seem to be an easy way find the size of a library on Unix.
+ // So this constant represents an approximation of the libcoreclr size (on debug build)
+ // that can be used to calculate an approximate location of the memory that
+ // is in 2GB range from the coreclr library. In addition, having precise size of libcoreclr
+ // is not necessary for the calculations.
+ const int32_t CoreClrLibrarySize = 100 * 1024 * 1024;
+
+ // This constant represent the max size of the virtual memory that this allocator
+ // will try to reserve during initialization. We want all JIT-ed code and the
+ // entire libcoreclr to be located in a 2GB range.
+ const int32_t MaxExecutableMemorySize = 0x7FFF0000 - CoreClrLibrarySize;
+
+ // Start address of the reserved virtual address space
+ void* m_startAddress;
+
+ // Next available address in the reserved address space
+ void* m_nextFreeAddress;
+
+ // Total size of the virtual memory that the allocator has been able to
+ // reserve during its initialization.
+ int32_t m_totalSizeOfReservedMemory;
+
+ // Remaining size of the reserved virtual memory that can be used to satisfy allocation requests.
+ int32_t m_remainingReservedMemory;
+};
+
+#endif // __cplusplus
+
+/*++
+Function :
+ ReserveMemoryFromExecutableAllocator
+
+ This function is used to reserve a region of virual memory (not commited)
+ that is located close to the coreclr library. The memory comes from the virtual
+ address range that is managed by ExecutableMemoryAllocator.
+--*/
+void* ReserveMemoryFromExecutableAllocator(CorUnix::CPalThread* pthrCurrent, SIZE_T allocationSize);
+
+#endif /* _PAL_VIRTUAL_H_ */
+
+
+
+
+
+
+