Initial work to port EventPipe library to NativeAOT (#80382)
authorLakshan Fernando <lakshanf@hotmail.com>
Wed, 8 Feb 2023 15:55:57 +0000 (07:55 -0800)
committerGitHub <noreply@github.com>
Wed, 8 Feb 2023 15:55:57 +0000 (07:55 -0800)
* CoreCLR shim files renamed to AOT

* change coreclr references to aot

* Native AOT runtime implementation

* hooks to EP library from AOT

* Container code

* Maanged to Native hooks

* build artifacts

* required changes to NativeAOT to support EP

* changes to common EP source

* sample EventSource test app

* Add EventPipe lib to the linker

* Additional conditions to include the EventPipe library

* Fixing the Checked and Release and Linux builds

* separating maanged and native EventSource switches

* Update src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
* FB, build break and test fixes

* fix non-windows build breaks and using paldebugbreak for TODOs

* trying another option to get arounf inttypes.h and PRIu64

* reverting the changes in ep-json file in common code

* Add an NativeAOT EventSource test

* FB and only enabling FEATURE_PERFTRACING in Windows

* fix DiagnosticEventSource test

* FB

* Update src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
* Added GuardCF version and a standalone test

* Moving NativeAOT headers away from EventPipe common code

* fix linux build break

* missed a needed definition in Linux

* inline eventpipe common source code

* Adding Evenpipe lib to a lib test

* Small cleanups

* Undo unnecessary changes
* Make sure runtime can build without FEATURE_PERFTRACING

* Fix linux build

---------

Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
39 files changed:
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
src/coreclr/nativeaot/Directory.Build.props
src/coreclr/nativeaot/Runtime/CMakeLists.txt
src/coreclr/nativeaot/Runtime/DisabledEventPipeInterface.cpp [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/EmptyContainers.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/EmptyContainers2.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/EnabledEventPipeInterface.cpp [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/EventPipeInterface.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/PalRedhawk.h
src/coreclr/nativeaot/Runtime/diagnosticserveradapter.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/NativeaotEventPipeSupport.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-config-aot.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipeadapter.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipeadaptertypes.h [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp [new file with mode: 0644]
src/coreclr/nativeaot/Runtime/startup.cpp
src/coreclr/nativeaot/Runtime/thread.h
src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp
src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp
src/coreclr/nativeaot/System.Private.CoreLib/src/System.Private.CoreLib.csproj
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.NativeAot.cs [new file with mode: 0644]
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
src/coreclr/tools/aot/ILCompiler/reproNative/reproNative.vcxproj
src/libraries/Microsoft.Extensions.Logging.EventSource/tests/Microsoft.Extensions.Logging.EventSource.Tests.csproj
src/libraries/System.Diagnostics.DiagnosticSource/tests/NativeAotTests/System.Diagnostics.DiagnosticSource.NativeAotTests.proj
src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs
src/libraries/System.Private.CoreLib/src/System/Threading/Overlapped.cs
src/native/eventpipe/ep-rt-config.h
src/tests/tracing/eventpipe/common/IpcTraceTest.cs
src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs [new file with mode: 0644]
src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj [new file with mode: 0644]

index d4a5f41..7036700 100644 (file)
@@ -45,6 +45,9 @@ The .NET Foundation licenses this file to you under the MIT license.
 
       <IlcRPath Condition="'$(IlcRPath)' == '' and '$(TargetOS)' != 'osx'">$ORIGIN</IlcRPath>
       <IlcRPath Condition="'$(IlcRPath)' == '' and '$(TargetOS)' == 'osx'">@executable_path</IlcRPath>
+
+      <EventPipeName>libeventpipe-disabled</EventPipeName>
+      <EventPipeName Condition="'$(EnableNativeEventPipe)' == 'true'">libeventpipe-enabled</EventPipeName>
     </PropertyGroup>
 
     <ItemGroup>
@@ -52,6 +55,7 @@ The .NET Foundation licenses this file to you under the MIT license.
       <NativeLibrary Condition="'$(NativeLib)' == ''" Include="$(IlcSdkPath)libbootstrapper.a" />
       <NativeLibrary Condition="'$(NativeLib)' != ''" Include="$(IlcSdkPath)libbootstrapperdll.a" />
       <NativeLibrary Include="$(IlcSdkPath)$(FullRuntimeName).a" />
+      <NativeLibrary Include="$(IlcSdkPath)$(EventPipeName)$(LibFileExt)" />
       <NativeLibrary Condition="'$(LinkStandardCPlusPlusLibrary)' != 'true' and '$(StaticICULinking)' != 'true'" Include="$(IlcSdkPath)libstdc++compat.a" />
       <NativeLibrary Condition="'$(StaticNumaLinking)' == 'true'" Include="$(IlcSdkPath)libnumasupportstatic.a" />
       <NativeLibrary Condition="'$(StaticNumaLinking)' != 'true'" Include="$(IlcSdkPath)libnumasupportdynamic.a" />
index fe5cdf1..5c11564 100644 (file)
@@ -25,6 +25,8 @@ The .NET Foundation licenses this file to you under the MIT license.
     <EntryPointSymbol Condition="'$(EntryPointSymbol)' == ''">wmainCRTStartup</EntryPointSymbol>
     <LinkerSubsystem Condition="'$(OutputType)' == 'WinExe' and '$(LinkerSubsystem)' == ''">WINDOWS</LinkerSubsystem>
     <LinkerSubsystem Condition="'$(OutputType)' == 'Exe' and '$(LinkerSubsystem)' == ''">CONSOLE</LinkerSubsystem>
+    <EventPipeName>eventpipe-disabled</EventPipeName>
+    <EventPipeName Condition="'$(EnableNativeEventPipe)' == 'true'">eventpipe-enabled</EventPipeName>
   </PropertyGroup>
 
   <!-- Ensure that runtime-specific paths have already been set -->
@@ -33,6 +35,7 @@ The .NET Foundation licenses this file to you under the MIT license.
     <ItemGroup>
       <NativeLibrary Include="$(IlcSdkPath)$(BootstrapperName)$(LibrarySuffix)" />
       <NativeLibrary Include="$(IlcSdkPath)$(FullRuntimeName)$(LibrarySuffix)" />
+      <NativeLibrary Include="$(IlcSdkPath)$(EventPipeName)$(LibrarySuffix)" />
       <NativeLibrary Condition="'$(IlcMultiModule)' == 'true'" Include="$(SharedLibrary)" />
     </ItemGroup>
 
index 275f039..337bffd 100644 (file)
   <PropertyGroup>
     <DefineConstants Condition="'$(FeatureObjCMarshal)' == 'true'">FEATURE_OBJCMARSHAL;$(DefineConstants)</DefineConstants>
   </PropertyGroup>
+  <PropertyGroup>
+    <FeaturePerfTracing>false</FeaturePerfTracing>
+    <FeaturePerfTracing Condition="'$(TargetsWindows)' == 'true'">true</FeaturePerfTracing>
+  </PropertyGroup>
+  <PropertyGroup>
+    <DefineConstants Condition="'$(FeaturePerfTracing)' == 'true'">FEATURE_PERFTRACING;$(DefineConstants)</DefineConstants>
+  </PropertyGroup>
+
 
   <!-- Platform specific properties -->
   <PropertyGroup Condition="'$(Platform)' == 'x64'">
index 69441fd..8c80cbe 100644 (file)
@@ -207,6 +207,14 @@ list(APPEND RUNTIME_SOURCES_ARCH_ASM
 convert_to_absolute_path(ARCH_SOURCES_DIR ${ARCH_SOURCES_DIR})
 include_directories(${ARCH_SOURCES_DIR})
 
+if(NOT CLR_CMAKE_TARGET_ARCH_WASM)
+  set(FEATURE_PERFTRACING 1)
+endif()
+
+if(FEATURE_PERFTRACING)
+  add_definitions(-DFEATURE_PERFTRACING)
+endif()
+
 add_definitions(-DFEATURE_BASICFREEZE)
 add_definitions(-DFEATURE_CONSERVATIVE_GC)
 add_definitions(-DFEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP)
@@ -263,6 +271,10 @@ else()
   add_subdirectory(Portable)
 endif()
 
+if(FEATURE_PERFTRACING)
+  add_subdirectory(eventpipe)
+endif()
+
 if (CLR_CMAKE_TARGET_UNIX)
   add_library(numasupportdynamic STATIC ${GC_DIR}/unix/numasupport.dynamic.cpp)
   install_static_library(numasupportdynamic aotsdk nativeaot)
diff --git a/src/coreclr/nativeaot/Runtime/DisabledEventPipeInterface.cpp b/src/coreclr/nativeaot/Runtime/DisabledEventPipeInterface.cpp
new file mode 100644 (file)
index 0000000..cb654d8
--- /dev/null
@@ -0,0 +1,12 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+void EventPipeAdapter_Initialize() {}
+
+bool DiagnosticServerAdapter_Initialize() { return false; }
+void DiagnosticServerAdapter_PauseForDiagnosticsMonitor() {}
+
+void EventPipeAdapter_FinishInitialize() {}
+
+void EventPipeAdapter_Shutdown() {}
+bool DiagnosticServerAdapter_Shutdown() { return false; }
diff --git a/src/coreclr/nativeaot/Runtime/EmptyContainers.h b/src/coreclr/nativeaot/Runtime/EmptyContainers.h
new file mode 100644 (file)
index 0000000..f96af50
--- /dev/null
@@ -0,0 +1,321 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __EmptyContainers_h__
+#define __EmptyContainers_h__
+
+// This header file will contains minimal containers that are needed for EventPipe library implementation
+// shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+// @TODO - this will likely be replaced by the common container classes to be added to the EventPipe library
+// Hence initially, the bare boned implementation focus is on unblocking HW/Simple Trace bring up
+
+#include "EmptyContainers2.h"
+#include "rhassert.h"
+
+struct SLink_EP
+{
+    SLink_EP* m_pNext;
+
+    SLink_EP()
+    {
+        m_pNext = NULL;
+    }
+
+    // find pLink within the list starting at pHead
+    // if found remove the link from the list and return the link
+    // otherwise return NULL
+    static SLink_EP* FindAndRemove(SLink_EP *pHead, SLink_EP* pLink, SLink_EP ** ppPrior)
+    {
+
+           _ASSERTE(pHead != NULL);
+           _ASSERTE(pLink != NULL);
+
+           SLink_EP* pFreeLink = NULL;
+        *ppPrior = NULL;
+
+           while (pHead->m_pNext != NULL)
+           {
+                   if (pHead->m_pNext == pLink)
+                   {
+                           pFreeLink = pLink;
+                           pHead->m_pNext = pLink->m_pNext;
+                *ppPrior = pHead;
+                break;
+                   }
+            pHead = pHead->m_pNext;
+           }
+
+           return pFreeLink;
+    }
+};
+
+
+// template <class T, bool fHead = false, typename __PTR = T*, SLink_EP T::*LinkPtr = &T::m_Link>
+// Assumes fHead to be false
+template <class T>
+class SList_EP
+{
+protected:
+    // used as sentinel
+    SLink_EP  m_link;
+    SLink_EP* m_pHead;
+    SLink_EP* m_pTail;
+
+    // get the list node within the object
+    static SLink_EP* GetLink (T* pLink)
+    {
+        return &(pLink->m_Link);
+    }
+
+    static T* GetObject (SLink_EP* pLink)
+    {
+        if (pLink == NULL)
+            return NULL;
+        return reinterpret_cast<T*>(reinterpret_cast<ptrdiff_t>(pLink) - offsetof(T, m_Link));
+     }
+
+public:
+
+    SList_EP()
+    {
+        m_pHead = &m_link;
+        // NOTE :: fHead variable is template argument
+        // the following code is a compiled in, only if the fHead flag
+        // is set to false,
+        m_pTail = &m_link;
+        // TODO: Likely not needed now since SLink_EP has a ctor
+        m_link.m_pNext = NULL;
+    }
+
+    bool IsEmpty()
+    {
+        return m_pHead->m_pNext == NULL;
+    }
+
+    void InsertTail(T *pObj)
+    {
+        _ASSERTE(pObj != NULL);
+        SLink_EP *pLink = GetLink(pObj);
+
+        m_pTail->m_pNext = pLink;
+        m_pTail = pLink;
+    }
+
+    T* RemoveHead()
+    {
+        SLink_EP* pLink = m_pHead->m_pNext;
+        if (pLink != NULL)
+        {
+            m_pHead->m_pNext = pLink->m_pNext;
+        }
+
+        if(m_pTail == pLink)
+        {
+            m_pTail = m_pHead;
+        }
+
+        return GetObject(pLink);
+    }
+
+    T* GetHead()
+    {
+        return GetObject(m_pHead->m_pNext);
+    }
+
+    static T *GetNext(T *pObj)
+    {
+        _ASSERTE(pObj != NULL);
+        return GetObject(GetLink(pObj)->m_pNext);
+    }
+
+
+    T* FindAndRemove(T *pObj)
+    {
+        _ASSERTE(pObj != NULL);
+
+        SLink_EP   *prior;
+        SLink_EP   *ret = SLink_EP::FindAndRemove(m_pHead, GetLink(pObj), &prior);
+
+        if (ret == m_pTail)
+            m_pTail = prior;
+
+        return GetObject(ret);
+    }
+
+    void InsertHead(T *pObj)
+    {
+        //PalDebugBreak();
+    }
+
+
+    class Iterator
+    {
+        friend class SList_EP;
+        //T* _t;
+
+    public:
+        Iterator & operator++()
+        { 
+            _ASSERTE(m_cur != NULL); 
+            m_cur = SList_EP::GetNext(m_cur); 
+            return *this; 
+        }
+
+        Iterator operator++(int)
+        { 
+            Iterator it(m_cur); 
+            ++(*this); 
+            return it; 
+        }
+
+        bool operator==(Iterator const & other) const
+        {
+            return m_cur == other.m_cur ||
+                   (m_cur != NULL && other.m_cur != NULL && *m_cur == *other.m_cur);
+        }
+
+        T & operator*() 
+        {
+            _ASSERTE(m_cur != NULL);
+            return *m_cur;
+        }
+
+        T * operator->() const 
+        {
+            //PalDebugBreak();
+            return m_cur;
+        }
+
+    private:
+        // Iterator(SList * pList)
+        //     : m_cur(pList->GetHead())
+        // { }
+
+        Iterator(T* pObj)
+            : m_cur(pObj)
+        { }
+
+        Iterator()
+            : m_cur(NULL)
+        { }
+
+        T* m_cur;
+
+    };
+
+    Iterator begin()
+    { 
+        return Iterator(GetHead()); 
+    }
+
+    Iterator end()
+    { 
+        return Iterator(); 
+    }
+
+};
+
+template <typename ElemT>
+struct SListElem_EP
+{
+    SLink_EP m_Link;
+    ElemT m_Value;
+
+    operator ElemT const &() const
+    { 
+        return m_Value; 
+    }
+
+    operator ElemT &()
+    { 
+        return m_Value; 
+    }
+
+    ElemT const & operator*() const
+    { 
+        //PalDebugBreak();
+        return m_Value; 
+    }
+
+    ElemT & operator*()
+    { 
+        //PalDebugBreak();
+        return m_Value; 
+    }
+
+    SListElem_EP()
+        : m_Link()
+        , m_Value()
+    { 
+    }
+
+    SListElem_EP(ElemT val)
+        : m_Link()
+        , m_Value(val)
+    { 
+    }
+
+    ElemT & GetValue()
+    { 
+        return m_Value; 
+    }    
+
+};
+
+// Bare boned implementation to unblock HW
+template <class T>
+class CQuickArrayList_EP
+{
+private:
+    size_t m_curSize;
+    T *m_array;
+    size_t maxSize;
+public:
+    CQuickArrayList_EP()
+        : m_curSize(0), maxSize(100)
+    {
+        m_array = new T[maxSize];
+    }
+
+
+    T* AllocNoThrow(size_t iItems)
+    {
+        return new T[iItems];
+    }
+
+    bool PushNoThrow(const T & value)
+    {
+        // if(m_curSize >= maxSize)
+        //     PalDebugBreak();
+        m_array[m_curSize++] = value;
+        return true;
+    }
+
+    size_t Size() const
+    {
+        return m_curSize;
+    }
+    
+    T Pop()
+    {
+        T t = m_array[m_curSize];
+        m_curSize--;
+        return t;
+    }
+
+    void Shrink()
+    {
+    }
+    
+    T& operator[] (size_t ix)
+    {
+        return m_array[ix];
+    }
+
+    T* Ptr()
+    {
+        return m_array;
+    }
+};
+
+#endif // __EmptyContainers_h__
diff --git a/src/coreclr/nativeaot/Runtime/EmptyContainers2.h b/src/coreclr/nativeaot/Runtime/EmptyContainers2.h
new file mode 100644 (file)
index 0000000..44036c2
--- /dev/null
@@ -0,0 +1,548 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __EmptyContainers2_h__
+#define __EmptyContainers2_h__
+
+// This header file will contains minimal containers that are needed for EventPipe library implementation
+// shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+// @TODO - this will likely be replaced by the common container classes to be added to the EventPipe library
+// Hence initially, the bare boned implementation focus is on unblocking HW/Simple Trace bring up
+
+// TODO: Should shash.h FailureType be used instead?
+enum FailureType_EP { ftAllocation_EP, ftOverflow_EP };
+
+template < typename ELEMENT, typename COUNT_T = uint32_t  >
+class DefaultSHashTraits_EP
+{
+public:
+    typedef COUNT_T count_t;
+    typedef ELEMENT element_t;
+    typedef element_t* PTR_element_t;
+
+    static const count_t s_growth_factor_numerator = 3;
+    static const count_t s_growth_factor_denominator = 2;
+
+    static const count_t s_density_factor_numerator = 3;
+    static const count_t s_density_factor_denominator = 4;
+
+    static const count_t s_minimum_allocation = 7;
+
+    static const bool s_NoThrow = true;
+
+    static const ELEMENT Null() { return (const ELEMENT) 0; }
+    static const ELEMENT Deleted() { return (const ELEMENT) -1; }
+    static bool IsNull(const ELEMENT &e) { return e == (const ELEMENT) 0; }
+    static bool IsDeleted(const ELEMENT &e) 
+    { 
+        //PalDebugBreak();
+        return false;
+        //return e == (const ELEMENT) -1;
+    }
+
+    static void OnFailure(FailureType_EP /*ft*/) { }
+
+};
+
+template <typename TRAITS>
+class SHash_EP : public TRAITS
+{
+  public:
+    class Index;
+    friend class Index;
+    class Iterator;
+
+    typedef typename TRAITS::element_t element_t;
+    typedef typename TRAITS::PTR_element_t PTR_element_t;
+    typedef typename TRAITS::key_t key_t;
+    typedef typename TRAITS::count_t count_t;
+
+    SHash_EP():m_table(nullptr),
+    m_tableSize(0),
+    m_tableCount(0),
+    m_tableOccupied(0),
+    m_tableMax(0)
+    {        
+    }
+
+    ~SHash_EP()
+    {
+        delete [] m_table;
+    }
+
+    const element_t * Lookup(element_t* table, count_t tableSize, key_t key) const
+    {
+        if (tableSize == 0)
+            return NULL;
+
+        count_t hash = TRAITS::Hash(key);
+        count_t index = hash % tableSize;
+        count_t increment = 0; // delay computation
+
+        while (true)
+        {
+            element_t& current = table[index];
+
+            if (TRAITS::IsNull(current))
+                return NULL;
+
+            if (!TRAITS::IsDeleted(current)
+                && TRAITS::Equals(key, TRAITS::GetKey(current)))
+            {
+                return &current;
+            }
+
+            if (increment == 0)
+                increment = (hash % (tableSize-1)) + 1;
+
+            index += increment;
+            if (index >= tableSize)
+                index -= tableSize;
+        }
+
+    }
+
+    const element_t* LookupPtr(key_t key) const
+    {
+        return Lookup(m_table, m_tableSize, key);        
+    }
+
+    bool Add(const element_t &element)
+    {
+        if (!CheckGrowth())
+            return false;
+
+        if (Add(m_table, m_tableSize, element))
+            m_tableOccupied++;
+        m_tableCount++;
+
+        return true;
+    }
+
+    bool CheckGrowth()
+    {
+        if (m_tableOccupied == m_tableMax)
+        {
+            return Grow();
+        }
+
+        return true;
+    }
+
+    bool Reallocate(count_t newTableSize)
+    {
+        // ASSERT(newTableSize >=
+        //             (count_t) (GetCount() * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator));
+
+        // Allocation size must be a prime number.  This is necessary so that hashes uniformly
+        // distribute to all indices, and so that chaining will visit all indices in the hash table.
+        newTableSize = NextPrime(newTableSize);
+        if (newTableSize == 0)
+        {
+            TRAITS::OnFailure(ftOverflow_EP);
+            return false;
+        }
+
+        element_t *newTable = new (nothrow) element_t [newTableSize];
+        if (newTable == NULL)
+        {
+            TRAITS::OnFailure(ftAllocation_EP);
+            return false;
+        }
+
+        element_t *p = newTable, *pEnd = newTable + newTableSize;
+        while (p < pEnd)
+        {
+            *p = TRAITS::Null();
+            p++;
+        }
+
+        for (Iterator i = Begin(), end = End(); i != end; i++)
+        {
+            const element_t & cur = (*i);
+            if (!TRAITS::IsNull(cur) && !TRAITS::IsDeleted(cur))
+                Add(newTable, newTableSize, cur);
+        }
+
+        // @todo:
+        // We might want to try to delay this cleanup to allow asynchronous readers
+
+        delete [] m_table;
+
+        m_table = PTR_element_t(newTable);
+        m_tableSize = newTableSize;
+        m_tableMax = (count_t) (newTableSize * TRAITS::s_density_factor_numerator / TRAITS::s_density_factor_denominator);
+        m_tableOccupied = m_tableCount;
+
+        return true;
+    }
+
+    //
+    // Enumerator, provides a template to produce an iterator on an existing class
+    // with a single iteration variable.
+    //
+
+    template <typename SUBTYPE>
+    class Enumerator
+    {
+     private:
+        const SUBTYPE *This() const
+        {
+            return (const SUBTYPE *) this;
+        }
+
+        SUBTYPE *This()
+        {
+            return (SUBTYPE *)this;
+        }
+
+      public:
+
+        Enumerator()
+        {
+        }
+
+        const element_t &operator*() const
+        {
+            return This()->Get();
+        }
+        const element_t *operator->() const
+        {
+            return &(This()->Get());
+        }
+        SUBTYPE &operator++()
+        {
+            This()->Next();
+            return *This();
+        }
+        SUBTYPE operator++(int)
+        {
+            SUBTYPE i = *This();
+            This()->Next();
+            return i;
+        }
+        bool operator==(const SUBTYPE &i) const
+        {
+            return This()->Equal(i);
+        }
+        bool operator!=(const SUBTYPE &i) const
+        {
+            return !This()->Equal(i);
+        }
+    };
+
+    //
+    // Index for whole table iterator.  This is also the base for the keyed iterator.
+    //
+
+    class Index
+    {
+        friend class SHash_EP;
+        friend class Iterator;
+        friend class Enumerator<Iterator>;
+
+        // The methods implementation has to be here for portability
+        // Some compilers won't compile the separate implementation in shash.inl
+      protected:
+
+        PTR_element_t m_table;
+        count_t m_tableSize;
+        count_t m_index;
+
+        Index(const SHash_EP *hash, bool begin)
+        : m_table(hash->m_table),
+            m_tableSize(hash->m_tableSize),
+            m_index(begin ? 0 : m_tableSize)
+        {
+        }
+
+        const element_t &Get() const
+        {
+            return m_table[m_index];
+        }
+
+        void First()
+        {
+            if (m_index < m_tableSize)
+                if (TRAITS::IsNull(m_table[m_index]) || TRAITS::IsDeleted(m_table[m_index]))
+                    Next();
+        }
+
+        void Next()
+        {
+            if (m_index >= m_tableSize)
+                return;
+
+            for (;;)
+            {
+                m_index++;
+                if (m_index >= m_tableSize)
+                    break;
+                if (!TRAITS::IsNull(m_table[m_index]) && !TRAITS::IsDeleted(m_table[m_index]))
+                    break;
+            }
+        }
+
+        bool Equal(const Index &i) const
+        {
+            return i.m_index == m_index;
+        }
+    };
+
+
+    class Iterator : public Index, public Enumerator<Iterator>
+    {
+        friend class SHash_EP;
+        TRAITS* _t;
+
+    public:
+        Iterator(const SHash_EP *hash, bool begin)
+          : Index(hash, begin)
+        {
+        }
+    };
+
+    Iterator Begin() const
+    {
+        Iterator i(this, true);
+        i.First();
+        return i;
+    }
+    Iterator End() const
+    {
+        return Iterator(this, false);
+    }
+    
+    bool AddNoThrow(const element_t &element)
+    {
+        //PalDebugBreak();
+        return false;
+    }
+    bool AddOrReplaceNoThrow(const element_t &element)
+    {
+        //PalDebugBreak();
+        return false;
+    }
+
+    count_t GetCount() const
+    {
+        return m_tableCount;
+    }
+
+    void Remove(key_t key)
+    {
+        //PalDebugBreak();
+    }
+
+    // Remove the specific element.
+    void Remove(Iterator& i)
+    {
+        //PalDebugBreak();
+    }
+    void RemoveAll()
+    {
+        delete [] m_table;
+
+        m_table = NULL;
+        m_tableSize = 0;
+        m_tableCount = 0;
+        m_tableOccupied = 0;
+        m_tableMax = 0;
+    }
+
+    // Instance members
+  private:
+    PTR_element_t  m_table;                // pointer to table
+    count_t       m_tableSize;            // allocated size of table
+    count_t       m_tableCount;           // number of elements in table
+    count_t       m_tableOccupied;        // number, includes deleted slots
+    count_t       m_tableMax;             // maximum occupied count before reallocating
+
+    bool Grow()
+    {
+        count_t newSize = (count_t) (m_tableCount
+                                    * TRAITS::s_growth_factor_numerator / TRAITS::s_growth_factor_denominator
+                                    * TRAITS::s_density_factor_denominator / TRAITS::s_density_factor_numerator);
+        if (newSize < TRAITS::s_minimum_allocation)
+            newSize = TRAITS::s_minimum_allocation;
+
+        // handle potential overflow
+        if (newSize < m_tableCount)
+        {
+            TRAITS::OnFailure(ftOverflow_EP);
+            return false;
+        }
+
+        return Reallocate(newSize);
+    }
+
+    static bool IsPrime(count_t number)
+    {
+        // This is a very low-tech check for primality, which doesn't scale very well.
+        // There are more efficient tests if this proves to be burdensome for larger
+        // tables.
+
+        if ((number&1) == 0)
+            return false;
+
+        count_t factor = 3;
+        while (factor * factor <= number)
+        {
+            if ((number % factor) == 0)
+                return false;
+            factor += 2;
+        }
+
+        return true;
+    }
+
+    static constexpr uint32_t g_shash_primes[] = {
+        11,17,23,29,37,47,59,71,89,107,131,163,197,239,293,353,431,521,631,761,919,
+        1103,1327,1597,1931,2333,2801,3371,4049,4861,5839,7013,8419,10103,12143,14591,
+        17519,21023,25229,30293,36353,43627,52361,62851,75431,90523, 108631, 130363,
+        156437, 187751, 225307, 270371, 324449, 389357, 467237, 560689, 672827, 807403,
+        968897, 1162687, 1395263, 1674319, 2009191, 2411033, 2893249, 3471899, 4166287,
+        4999559, 5999471, 7199369 };
+
+    // Returns a prime larger than 'number' or 0, in case of overflow
+    static count_t NextPrime(count_t number)
+    {
+        for (int i = 0; i < (int) (sizeof(g_shash_primes) / sizeof(g_shash_primes[0])); i++)
+        {
+            if (g_shash_primes[i] >= number)
+                return (typename SHash_EP<TRAITS>::count_t)(g_shash_primes[i]);
+        }
+
+        if ((number&1) == 0)
+            number++;
+
+        while (number != 1)
+        {
+            if (IsPrime(number))
+                return number;
+            number += 2;
+        }
+
+        return 0;
+    }
+
+    static bool Add(element_t *table, count_t tableSize, const element_t &element)
+    {
+        key_t key = TRAITS::GetKey(element);
+
+        count_t hash = TRAITS::Hash(key);
+        count_t index = hash % tableSize;
+        count_t increment = 0; // delay computation
+
+        while (true)
+        {
+            element_t& current = table[index];
+
+            if (TRAITS::IsNull(current))
+            {
+                table[index] = element;
+                return true;
+            }
+
+            if (TRAITS::IsDeleted(current))
+            {
+                table[index] = element;
+                return false;
+            }
+
+            if (increment == 0)
+                increment = (hash % (tableSize-1)) + 1;
+
+            index += increment;
+            if (index >= tableSize)
+                index -= tableSize;
+        }
+    }
+
+};
+
+template <typename KEY, typename VALUE>
+class KeyValuePair_EP{
+    KEY     key;
+    VALUE   value;
+
+public:
+    KeyValuePair_EP()
+    {
+    }
+
+    KeyValuePair_EP(const KEY& k, const VALUE& v)
+        : key(k), value(v)
+    {
+    }
+
+    KEY const & Key() const
+    {
+        return key;
+    }
+
+    VALUE const & Value() const
+    {
+        return value;
+    }
+};
+
+template <typename PARENT>
+class NoRemoveSHashTraits_EP : public PARENT
+{
+public:
+    typedef typename PARENT::element_t element_t;
+    typedef typename PARENT::count_t count_t;
+};
+
+template <typename KEY, typename VALUE>
+class MapSHashTraits_EP : public DefaultSHashTraits_EP< KeyValuePair_EP<KEY,VALUE> >
+{
+public:
+    typedef typename DefaultSHashTraits_EP< KeyValuePair_EP<KEY,VALUE> >::element_t element_t;
+    typedef typename DefaultSHashTraits_EP< KeyValuePair_EP<KEY,VALUE> >::count_t count_t;
+
+    typedef KEY key_t;
+    typedef VALUE value_t;
+
+    static key_t GetKey(element_t e)
+    {
+        return e.Key();
+    }
+    static bool Equals(key_t k1, key_t k2)
+    {
+        return k1 == k2;
+    }
+    static count_t Hash(key_t k)
+    {
+        return (count_t)(size_t)k;
+    }
+
+    static const element_t Null() 
+    { 
+        return element_t(KEY(),VALUE());
+    }
+    static bool IsNull(const element_t &e) 
+    { 
+        return e.Key() == KEY();
+    }
+    static bool IsDeleted(const element_t &e) 
+    { 
+        return e.Key() == KEY(-1); 
+    }
+
+    key_t const & Key() const
+    {
+        //PalDebugBreak();
+        return *(new KEY());
+    }
+
+    value_t const & Value() const
+    {
+        //PalDebugBreak();
+        return *(new VALUE());
+    }
+};
+
+
+#endif // __EmptyContainers2_h__
diff --git a/src/coreclr/nativeaot/Runtime/EnabledEventPipeInterface.cpp b/src/coreclr/nativeaot/Runtime/EnabledEventPipeInterface.cpp
new file mode 100644 (file)
index 0000000..a94cdd0
--- /dev/null
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "eventpipeadapter.h"
+#include "diagnosticserveradapter.h"
+
+#include "gcenv.h"
+#include "regdisplay.h"
+#include "StackFrameIterator.h"
+#include "thread.h"
+#include "SpinLock.h"
+
+void EventPipeAdapter_Initialize() { EventPipeAdapter::Initialize(); }
+
+bool DiagnosticServerAdapter_Initialize() { return DiagnosticServerAdapter::Initialize(); }
+void DiagnosticServerAdapter_PauseForDiagnosticsMonitor() { DiagnosticServerAdapter::PauseForDiagnosticsMonitor();}
+
+
+void EventPipeAdapter_FinishInitialize() { EventPipeAdapter::FinishInitialize(); }
+
+void EventPipeAdapter_Shutdown() { EventPipeAdapter::Shutdown(); }
+bool DiagnosticServerAdapter_Shutdown() { return DiagnosticServerAdapter::Shutdown(); }
diff --git a/src/coreclr/nativeaot/Runtime/EventPipeInterface.h b/src/coreclr/nativeaot/Runtime/EventPipeInterface.h
new file mode 100644 (file)
index 0000000..8015bc8
--- /dev/null
@@ -0,0 +1,19 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+#ifndef __EVENTPIPE_INTERFACE_H__
+#define __EVENTPIPE_INTERFACE_H__
+
+// Initialize EventPipe
+void EventPipeAdapter_Initialize();
+
+// Initialize DS
+bool DiagnosticServerAdapter_Initialize();
+void DiagnosticServerAdapter_PauseForDiagnosticsMonitor();
+
+
+void EventPipeAdapter_FinishInitialize();
+
+void EventPipeAdapter_Shutdown();
+bool DiagnosticServerAdapter_Shutdown();
+
+#endif //__EVENTPIPE_INTERFACE_H__
\ No newline at end of file
index f758883..44ba7ea 100644 (file)
@@ -742,6 +742,7 @@ REDHAWK_PALIMPORT void* REDHAWK_PALAPI PalAddVectoredExceptionHandler(uint32_t f
 typedef uint32_t (__stdcall *BackgroundCallback)(_In_opt_ void* pCallbackContext);
 REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartBackgroundGCThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext);
 REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext);
+REDHAWK_PALIMPORT bool REDHAWK_PALAPI PalStartEventPipeHelperThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext);
 
 typedef void (*PalHijackCallback)(_In_ NATIVE_CONTEXT* pThreadContext, _In_opt_ void* pThreadToHijack);
 REDHAWK_PALIMPORT void REDHAWK_PALAPI PalHijack(HANDLE hThread, _In_opt_ void* pThreadToHijack);
diff --git a/src/coreclr/nativeaot/Runtime/diagnosticserveradapter.h b/src/coreclr/nativeaot/Runtime/diagnosticserveradapter.h
new file mode 100644 (file)
index 0000000..62cd581
--- /dev/null
@@ -0,0 +1,42 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __DIAGNOSTIC_SERVER_ADAPTER_H__
+#define __DIAGNOSTIC_SERVER_ADAPTER_H__
+
+#if defined(FEATURE_PERFTRACING)
+
+#include <eventpipe/ds-server.h>
+
+class DiagnosticServerAdapter final
+{
+public:
+    static inline bool Initialize()
+    {
+        return ds_server_init();
+    }
+
+    static inline bool Shutdown()
+    {
+        return ds_server_shutdown();
+    }
+
+    NOINLINE static void PauseForDiagnosticsMonitor()
+    {
+        return ds_server_pause_for_diagnostics_monitor();
+    }
+
+    static void ResumeRuntimeStartup()
+    {
+        return ds_server_resume_runtime_startup();
+    }
+
+    static bool IsPausedInRuntimeStartup()
+    {
+        return ds_server_is_paused_in_startup();
+    }
+};
+
+#endif // FEATURE_PERFTRACING
+
+#endif // __DIAGNOSTIC_SERVER_ADAPTER_H__
diff --git a/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp b/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp
new file mode 100644 (file)
index 0000000..b1464bd
--- /dev/null
@@ -0,0 +1,104 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "common.h"
+#include "eventpipeadapter.h"
+
+#ifdef FEATURE_PERFTRACING
+
+#include "gcenv.h"
+#include "regdisplay.h"
+#include "StackFrameIterator.h"
+#include "thread.h"
+#include "SpinLock.h"
+
+struct EventPipeEventInstanceData;
+
+struct EventPipeSessionInfo;
+
+EXTERN_C NATIVEAOT_API uint64_t __cdecl RhEventPipeInternal_Enable(
+    LPCWSTR outputFile,
+    EventPipeSerializationFormat format,
+    uint32_t circularBufferSizeInMB,
+    /* COR_PRF_EVENTPIPE_PROVIDER_CONFIG */ const void * pProviders,
+    uint32_t numProviders)
+{
+    PalDebugBreak();
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_Disable(uint64_t sessionID)
+{
+    PalDebugBreak();
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_CreateProvider(
+    LPCWSTR providerName,
+    EventPipeCallback pCallbackFunc,
+    void* pCallbackContext)
+{
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_DefineEvent(
+    intptr_t provHandle,
+    uint32_t eventID,
+    int64_t keywords,
+    uint32_t eventVersion,
+    uint32_t level,
+    void *pMetadata,
+    uint32_t metadataLength)
+{
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_GetProvider(LPCWSTR providerName)
+{
+    PalDebugBreak();
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_DeleteProvider(intptr_t provHandle)
+{
+}
+
+EXTERN_C NATIVEAOT_API int __cdecl RhEventPipeInternal_EventActivityIdControl(uint32_t controlCode, GUID *pActivityId)
+{
+    PalDebugBreak();
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_WriteEventData(
+    intptr_t eventHandle,
+    EventData *pEventData,
+    uint32_t eventDataCount,
+    const GUID * pActivityId,
+    const GUID * pRelatedActivityId)
+{
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_GetSessionInfo(uint64_t sessionID, EventPipeSessionInfo *pSessionInfo)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_GetNextEvent(uint64_t sessionID, EventPipeEventInstanceData *pInstance)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_SignalSession(uint64_t sessionID)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_WaitForSessionSignal(uint64_t sessionID, int32_t timeoutMs)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+#endif // FEATURE_PERFTRACING
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt
new file mode 100644 (file)
index 0000000..39d658d
--- /dev/null
@@ -0,0 +1,99 @@
+project(Runtime)
+
+set(EP_GENERATED_HEADER_PATH "${GENERATED_INCLUDE_DIR}")
+include (${CLR_SRC_NATIVE_DIR}/eventpipe/configure.cmake)
+include_directories(${EP_GENERATED_HEADER_PATH})
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(AOT_EVENTPIPE_SHIM_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
+
+set (EVENTPIPE_SOURCES "")
+set (EVENTPIPE_HEADERS "")
+set (CORECLR_EVENTPIPE_SHIM_SOURCES "")
+set (CORECLR_EVENTPIPE_SHIM_HEADERS "")
+
+set (SHARED_EVENTPIPE_SOURCE_PATH "${CLR_SRC_NATIVE_DIR}/eventpipe")
+include (${SHARED_EVENTPIPE_SOURCE_PATH}/CMakeLists.txt)
+
+list(APPEND SHARED_DIAGNOSTIC_SERVER_SOURCES
+    ds-ipc-pal-namedpipe.c
+)
+
+list(APPEND SHARED_DIAGNOSTIC_SERVER_HEADERS
+    ds-ipc-pal-namedpipe.h
+)
+
+list(APPEND EVENTPIPE_SOURCES
+  ${SHARED_EVENTPIPE_SOURCES}
+  ${SHARED_DIAGNOSTIC_SERVER_SOURCES}
+)
+
+list(APPEND EVENTPIPE_HEADERS
+  ${SHARED_EVENTPIPE_HEADERS}
+  ${SHARED_DIAGNOSTIC_SERVER_HEADERS}
+)
+
+addprefix(EVENTPIPE_SOURCES ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_SOURCES}")
+addprefix(EVENTPIPE_HEADERS ${SHARED_EVENTPIPE_SOURCE_PATH} "${EVENTPIPE_HEADERS}")
+
+set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ep-sources.c PROPERTIES COMPILE_DEFINITIONS EP_FORCE_INCLUDE_SOURCE_FILES)
+set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ds-sources.c PROPERTIES COMPILE_DEFINITIONS DS_FORCE_INCLUDE_SOURCE_FILES)
+
+set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES LANGUAGE CXX)
+
+if(CLR_CMAKE_HOST_UNIX)
+  if (CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11)
+    set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES COMPILE_OPTIONS -xc++)
+  else(CMAKE_VERSION VERSION_GREATER 3.11 OR CMAKE_VERSION VERSION_EQUAL 3.11)
+    add_compile_options(-xc++)
+  endif()
+endif(CLR_CMAKE_HOST_UNIX)
+
+if (WIN32)
+    set_source_files_properties(${EVENTPIPE_SOURCES} PROPERTIES COMPILE_FLAGS "/FI\"${RUNTIME_DIR}/eventpipe/NativeaotEventPipeSupport.h\"")
+endif()
+
+list(APPEND AOT_EVENTPIPE_SHIM_SOURCES
+  ${AOT_EVENTPIPE_SHIM_DIR}/ep-rt-aot.cpp
+)
+
+list(APPEND AOT_EVENTPIPE_SHIM_HEADERS
+  ${AOT_EVENTPIPE_SHIM_DIR}/ds-rt-aot.h
+  ${AOT_EVENTPIPE_SHIM_DIR}/ds-rt-types-aot.h
+  ${AOT_EVENTPIPE_SHIM_DIR}/ep-rt-aot.h
+  ${AOT_EVENTPIPE_SHIM_DIR}/ep-rt-config-aot.h
+  ${AOT_EVENTPIPE_SHIM_DIR}/ep-rt-types-aot.h
+)
+
+list(APPEND AOT_EVENTPIPE_MANAGED_TO_NATIVE_SOURCES
+   ${RUNTIME_DIR}/eventpipeinternal.cpp
+   ${RUNTIME_DIR}/eventpipeadapter.h
+   ${RUNTIME_DIR}/diagnosticserveradapter.h
+   ${RUNTIME_DIR}/EnabledEventPipeInterface.cpp
+)
+
+list(APPEND EVENTPIPE_SOURCES
+  ${AOT_EVENTPIPE_SHIM_SOURCES}
+  ${AOT_EVENTPIPE_SHIM_HEADERS}
+  ${AOT_EVENTPIPE_MANAGED_TO_NATIVE_SOURCES}
+  ${SHARED_EVENTPIPE_CONFIG_HEADERS}
+)
+
+list(APPEND AOT_EVENTPIPE_DISABLED_SOURCES
+  ${RUNTIME_DIR}/DisabledEventPipeInterface.cpp
+  ${RUNTIME_DIR}/disabledeventpipeinternal.cpp
+)
+
+add_library(eventpipe-enabled STATIC ${EVENTPIPE_SOURCES})
+add_library(eventpipe-disabled STATIC ${AOT_EVENTPIPE_DISABLED_SOURCES})
+
+if (CLR_CMAKE_TARGET_WIN32)
+  add_library(eventpipe-disabled.GuardCF STATIC ${AOT_EVENTPIPE_DISABLED_SOURCES})
+  target_compile_options(eventpipe-disabled.GuardCF PRIVATE $<$<OR:$<COMPILE_LANGUAGE:C>,$<COMPILE_LANGUAGE:CXX>>:/guard:cf>)
+endif (CLR_CMAKE_TARGET_WIN32)
+
+install_static_library(eventpipe-enabled aotsdk nativeaot)
+install_static_library(eventpipe-disabled aotsdk nativeaot)
+if (CLR_CMAKE_TARGET_WIN32)
+  install_static_library(eventpipe-disabled.GuardCF aotsdk nativeaot)
+endif (CLR_CMAKE_TARGET_WIN32)
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/NativeaotEventPipeSupport.h b/src/coreclr/nativeaot/Runtime/eventpipe/NativeaotEventPipeSupport.h
new file mode 100644 (file)
index 0000000..253f147
--- /dev/null
@@ -0,0 +1,22 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __NativeaotEventPipeSupport_h__
+#define __NativeaotEventPipeSupport_h__
+
+// This file is included only when compiling shared EventPipe source files and contains any
+// definitions which are needed by these source files but are not available in NativeAOT
+// runtime source files.
+
+// As mentioned PalRedhawk*.cpp, in general we don't want to assume that Windows and
+// Redhawk global definitions can co-exist, meaning NativeAOT runtime source files
+// generally do not have access to windows.h; that said, the HOST_WIN32 parts of the shared
+// EventPipe code are designed to rely on windows.h, so windows.h must be included when
+// compiling shared EventPipe source files, and a marker is set to indicate that windows.h
+// has been added to the compilation in this manner.
+
+#include <windows.h>
+
+#define BUILDING_SHARED_NATIVEAOT_EVENTPIPE_CODE
+
+#endif // __NativeaotEventPipeSupport_h__
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h
new file mode 100644 (file)
index 0000000..8b09c8e
--- /dev/null
@@ -0,0 +1,319 @@
+// Implementation of ds-rt.h targeting AOT runtime.
+#ifndef __DIAGNOSTICS_RT_AOT_H__
+#define __DIAGNOSTICS_RT_AOT_H__
+
+#include <eventpipe/ds-rt-config.h>
+
+#ifdef ENABLE_PERFTRACING
+#include "ep-rt-aot.h"
+#include <eventpipe/ds-process-protocol.h>
+#include <eventpipe/ds-profiler-protocol.h>
+#include <eventpipe/ds-dump-protocol.h>
+
+#undef DS_LOG_ALWAYS_0
+#define DS_LOG_ALWAYS_0(msg) do {} while (0)
+
+#undef DS_LOG_ALWAYS_1
+#define DS_LOG_ALWAYS_1(msg, data1) do {} while (0)
+
+#undef DS_LOG_ALWAYS_2
+#define DS_LOG_ALWAYS_2(msg, data1, data2) do {} while (0)
+
+#undef DS_LOG_INFO_0
+#define DS_LOG_INFO_0(msg) do {} while (0)
+
+#undef DS_LOG_INFO_1
+#define DS_LOG_INFO_1(msg, data1) do {} while (0)
+
+#undef DS_LOG_INFO_2
+#define DS_LOG_INFO_2(msg, data1, data2) do {} while (0)
+
+#undef DS_LOG_ERROR_0
+#define DS_LOG_ERROR_0(msg) do {} while (0)
+
+#undef DS_LOG_ERROR_1
+#define DS_LOG_ERROR_1(msg, data1) do {} while (0)
+
+#undef DS_LOG_ERROR_2
+#define DS_LOG_ERROR_2(msg, data1, data2) do {} while (0)
+
+#undef DS_LOG_WARNING_0
+#define DS_LOG_WARNING_0(msg) do {} while (0)
+
+#undef DS_LOG_WARNING_1
+#define DS_LOG_WARNING_1(msg, data1) do {} while (0)
+
+#undef DS_LOG_WARNING_2
+#define DS_LOG_WARNING_2(msg, data1, data2) do {} while (0)
+
+#undef DS_LOG_DEBUG_0
+#define DS_LOG_DEBUG_0(msg) do {} while (0)
+
+#undef DS_LOG_DEBUG_1
+#define DS_LOG_DEBUG_1(msg, data1) do {} while (0)
+
+#undef DS_LOG_DEBUG_2
+#define DS_LOG_DEBUG_2(msg, data1, data2) do {} while (0)
+
+#undef DS_ENTER_BLOCKING_PAL_SECTION
+#define DS_ENTER_BLOCKING_PAL_SECTION
+
+#undef DS_EXIT_BLOCKING_PAL_SECTION
+#define DS_EXIT_BLOCKING_PAL_SECTION
+
+#undef DS_RT_DEFINE_ARRAY
+#define DS_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type)
+
+#undef DS_RT_DEFINE_LOCAL_ARRAY
+#define DS_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ds, array_name, array_type, iterator_type, item_type)
+
+#undef DS_RT_DEFINE_ARRAY_ITERATOR
+#define DS_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type)
+
+#undef DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR
+#define DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ds, array_name, array_type, iterator_type, item_type)
+
+/*
+* AutoTrace.
+*/
+
+#ifdef FEATURE_AUTO_TRACE
+#include "autotrace.h"
+#endif
+
+static
+void
+ds_rt_auto_trace_init (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef FEATURE_AUTO_TRACE
+    auto_trace_init ();
+#endif
+}
+
+static
+void
+ds_rt_auto_trace_launch (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef FEATURE_AUTO_TRACE
+    auto_trace_launch ();
+#endif
+}
+
+static
+void
+ds_rt_auto_trace_signal (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef FEATURE_AUTO_TRACE
+    auto_trace_signal ();
+#endif
+}
+
+static
+void
+ds_rt_auto_trace_wait (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef FEATURE_AUTO_TRACE
+    auto_trace_wait ();
+#endif
+}
+
+/*
+ * DiagnosticsConfiguration.
+ */
+
+static
+inline
+bool
+ds_rt_config_value_get_enable (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    return true;
+}
+
+static
+inline
+ep_char8_t *
+ds_rt_config_value_get_ports (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    return nullptr;
+}
+
+static
+inline
+uint32_t
+ds_rt_config_value_get_default_port_suspend (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    return 0;
+}
+
+/*
+* DiagnosticsDump.
+*/
+
+static
+ds_ipc_result_t
+ds_rt_generate_core_dump (
+    DiagnosticsDumpCommandId commandId,
+    DiagnosticsGenerateCoreDumpCommandPayload *payload,
+    ep_char8_t *errorMessageBuffer,
+    int32_t cbErrorMessageBuffer)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    ds_ipc_result_t result = DS_IPC_E_FAIL;
+    uint32_t flags = ds_generate_core_dump_command_payload_get_flags(payload);
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Generate an exception dump
+    // PalDebugBreak();
+
+    return 0;
+}
+
+/*
+ * DiagnosticsIpc.
+ */
+
+static
+inline
+bool
+ds_rt_transport_get_default_name (
+    ep_char8_t *name,
+    int32_t name_len,
+    const ep_char8_t *prefix,
+    int32_t id,
+    const ep_char8_t *group_id,
+    const ep_char8_t *suffix)
+{
+    STATIC_CONTRACT_NOTHROW;
+    
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: PAL_GetTransportName is defined in coreclr\pal\inc\pal.h
+    return true;
+}
+
+/*
+ * DiagnosticsIpcPollHandle.
+ */
+
+DS_RT_DEFINE_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle)
+DS_RT_DEFINE_LOCAL_ARRAY (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle)
+DS_RT_DEFINE_ARRAY_ITERATOR (ipc_poll_handle_array, ds_rt_ipc_poll_handle_array_t, ds_rt_ipc_poll_handle_array_iterator_t, DiagnosticsIpcPollHandle)
+
+#undef DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY
+#define DS_RT_DECLARE_LOCAL_IPC_POLL_HANDLE_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_ipc_poll_handle_array_t)
+
+/*
+ * DiagnosticsPort.
+ */
+
+DS_RT_DEFINE_ARRAY (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *)
+DS_RT_DEFINE_ARRAY_ITERATOR (port_array, ds_rt_port_array_t, ds_rt_port_array_iterator_t, DiagnosticsPort *)
+
+DS_RT_DEFINE_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *)
+DS_RT_DEFINE_LOCAL_ARRAY (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *)
+DS_RT_DEFINE_ARRAY_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_iterator_t, ep_char8_t *)
+DS_RT_DEFINE_ARRAY_REVERSE_ITERATOR (port_config_array, ds_rt_port_config_array_t, ds_rt_port_config_array_reverse_iterator_t, ep_char8_t *)
+
+#undef DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY
+#define DS_RT_DECLARE_LOCAL_PORT_CONFIG_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ds_rt_port_config_array_t)
+
+/*
+* DiagnosticsProfiler.
+*/
+#ifdef PROFILING_SUPPORTED
+#include "profilinghelper.h"
+#include "profilinghelper.inl"
+
+#ifdef FEATURE_PROFAPI_ATTACH_DETACH
+static
+uint32_t
+ds_rt_profiler_attach (DiagnosticsAttachProfilerCommandPayload *payload)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (!g_profControlBlock.fProfControlBlockInitialized)
+        return DS_IPC_E_RUNTIME_UNINITIALIZED;
+
+    // Certain actions are only allowable during attach, and this flag is how we track it.
+    ClrFlsSetThreadType (ThreadType_ProfAPI_Attach);
+
+    HRESULT hr = S_OK;
+    hr = ProfilingAPIUtility::LoadProfilerForAttach (reinterpret_cast<const CLSID *>(ds_attach_profiler_command_payload_get_profiler_guid_cref (payload)),
+        reinterpret_cast<LPCWSTR>(ds_attach_profiler_command_payload_get_profiler_path (payload)),
+        reinterpret_cast<LPVOID>(ds_attach_profiler_command_payload_get_client_data (payload)),
+        static_cast<UINT>(ds_attach_profiler_command_payload_get_client_data_len (payload)),
+        static_cast<DWORD>(ds_attach_profiler_command_payload_get_attach_timeout (payload)));
+
+    // Clear the flag so this thread isn't permanently marked as the attach thread.
+    ClrFlsClearThreadType (ThreadType_ProfAPI_Attach);
+
+    return hr;
+}
+#endif // FEATURE_PROFAPI_ATTACH_DETACH
+
+static
+uint32_t
+ds_rt_profiler_startup (DiagnosticsStartupProfilerCommandPayload *payload)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    HRESULT hr = S_OK;
+    StoredProfilerNode *profilerData = new StoredProfilerNode();
+    profilerData->guid = *(reinterpret_cast<const CLSID *>(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)));
+    profilerData->path.Set(reinterpret_cast<LPCWSTR>(ds_startup_profiler_command_payload_get_profiler_path (payload)));
+
+    g_profControlBlock.storedProfilers.InsertHead(profilerData);
+
+    return hr;
+}
+#endif // PROFILING_SUPPORTED
+
+static
+uint32_t
+ds_rt_set_environment_variable (const ep_char16_t *name, const ep_char16_t *value)
+{
+     // return SetEnvironmentVariableW(reinterpret_cast<LPCWSTR>(name), reinterpret_cast<LPCWSTR>(value)) ? S_OK : HRESULT_FROM_WIN32(GetLastError());
+     // PalDebugBreak();
+    return 0xffff;
+}
+
+/*
+* DiagnosticServer.
+*/
+
+static
+void
+ds_rt_server_log_pause_message (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    const char diagPortsName[] = "DOTNET_DiagnosticPorts";
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Cannot find nocache versions of RhConfig
+    // PalDebugBreak();
+}
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __DIAGNOSTICS_RT_AOT_H__ */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h
new file mode 100644 (file)
index 0000000..9c01f9f
--- /dev/null
@@ -0,0 +1,40 @@
+// Implementation of ds-rt-types.h targeting CoreCLR runtime.
+#ifndef __DIAGNOSTICS_RT_TYPES_AOT_H__
+#define __DIAGNOSTICS_RT_TYPES_AOT_H__
+
+#include <eventpipe/ds-rt-config.h>
+
+#ifdef ENABLE_PERFTRACING
+#include "ep-rt-types-aot.h"
+
+/*
+ * DiagnosticsIpcPollHandle.
+ */
+
+#undef ds_rt_ipc_poll_handle_array_t
+typedef struct _rt_aot_array_internal_t<DiagnosticsIpcPollHandle> ds_rt_ipc_poll_handle_array_t;
+
+#undef ds_rt_ipc_poll_handle_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<DiagnosticsIpcPollHandle> ds_rt_ipc_poll_handle_array_iterator_t;
+
+/*
+ * DiagnosticsPort.
+ */
+
+#undef ds_rt_port_array_t
+typedef struct _rt_aot_array_internal_t<DiagnosticsPort *> ds_rt_port_array_t;
+
+#undef ds_rt_port_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<DiagnosticsPort *> ds_rt_port_array_iterator_t;
+
+#undef ds_rt_port_config_array_t
+typedef struct _rt_aot_array_internal_t<ep_char8_t *> ds_rt_port_config_array_t;
+
+#undef ds_rt_port_config_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<ep_char8_t *> ds_rt_port_config_array_iterator_t;
+
+#undef ds_rt_port_config_array_reverse_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<ep_char8_t *> ds_rt_port_config_array_reverse_iterator_t;
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __DIAGNOSTICS_RT_TYPES_AOT_H__ */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp
new file mode 100644 (file)
index 0000000..ad1951f
--- /dev/null
@@ -0,0 +1,502 @@
+#include <eventpipe/ep-rt-config.h>
+
+#ifdef ENABLE_PERFTRACING
+#include <eventpipe/ep-types.h>
+#include <eventpipe/ep.h>
+#include <eventpipe/ep-stack-contents.h>
+#include <eventpipe/ep-rt.h>
+
+// The regdisplay.h, StackFrameIterator.h, and thread.h includes are present only to access the Thread
+// class and can be removed if it turns out that the required ep_rt_thread_handle_t can be
+// implemented in some manner that doesn't rely on the Thread class.
+
+#include "gcenv.h"
+#include "regdisplay.h"
+#include "StackFrameIterator.h"
+#include "thread.h"
+#include "holder.h"
+#include "SpinLock.h"
+
+ep_rt_lock_handle_t _ep_rt_aot_config_lock_handle;
+CrstStatic _ep_rt_aot_config_lock;
+
+thread_local EventPipeAotThreadHolderTLS EventPipeAotThreadHolderTLS::g_threadHolderTLS;
+
+ep_char8_t *volatile _ep_rt_aot_diagnostics_cmd_line;
+
+#ifndef TARGET_UNIX
+uint32_t *_ep_rt_aot_proc_group_offsets;
+#endif
+
+/*
+ * Forward declares of all static functions.
+ */
+
+
+static
+void
+walk_managed_stack_for_threads (
+    ep_rt_thread_handle_t sampling_thread,
+    EventPipeEvent *sampling_event);
+
+
+bool
+ep_rt_aot_walk_managed_stack_for_thread (
+    ep_rt_thread_handle_t thread,
+    EventPipeStackContents *stack_contents)
+{
+    PalDebugBreak();
+    return false;
+}
+
+// The thread store lock must already be held by the thread before this function
+// is called.  ThreadSuspend::SuspendEE acquires the thread store lock.
+static
+void
+walk_managed_stack_for_threads (
+    ep_rt_thread_handle_t sampling_thread,
+    EventPipeEvent *sampling_event)
+{
+}
+
+void
+ep_rt_aot_sample_profiler_write_sampling_event_for_threads (
+    ep_rt_thread_handle_t sampling_thread,
+    EventPipeEvent *sampling_event)
+{
+}
+
+const ep_char8_t *
+ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) 
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe assembly name - return filename in nativeaot?
+    PalDebugBreak();
+
+    // fallback to the empty string if we can't get assembly info, e.g., if the runtime is
+    // suspended before an assembly is loaded.
+    return reinterpret_cast<const ep_char8_t*>("");
+}
+
+uint32_t
+ep_rt_aot_atomic_inc_uint32_t (volatile uint32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return static_cast<uint32_t>(PalInterlockedIncrement ((volatile int32_t *)(value)));
+}
+
+uint32_t
+ep_rt_aot_atomic_dec_uint32_t (volatile uint32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return static_cast<uint32_t>(PalInterlockedDecrement ((volatile int32_t *)(value)));
+}
+
+int32_t
+ep_rt_aot_atomic_inc_int32_t (volatile int32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+   return static_cast<int32_t>(PalInterlockedIncrement (value));
+}
+
+int32_t
+ep_rt_aot_atomic_dec_int32_t (volatile int32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+   return static_cast<int32_t>(PalInterlockedDecrement (value));
+}
+
+int64_t
+ep_rt_aot_atomic_inc_int64_t (volatile int64_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Consider replacing with a new PalInterlockedIncrement64 service
+    int64_t currentValue;
+    do {
+        currentValue = *value;
+    } while (currentValue != PalInterlockedCompareExchange64(value, (currentValue + 1), currentValue));
+
+    // The current value has been atomically replaced with the incremented value.
+    return (currentValue + 1);
+}
+
+int64_t
+ep_rt_aot_atomic_dec_int64_t (volatile int64_t *value) { 
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Consider replacing with a new PalInterlockedDecrement64 service
+    int64_t currentValue;
+    do {
+        currentValue = *value;
+    } while (currentValue != PalInterlockedCompareExchange64(value, (currentValue - 1), currentValue));
+
+    // The current value has been atomically replaced with the decremented value.
+    return (currentValue - 1);
+}
+
+size_t
+ep_rt_aot_atomic_compare_exchange_size_t (volatile size_t *target, size_t expected, size_t value) {
+    STATIC_CONTRACT_NOTHROW;
+#ifdef HOST_64BIT
+    return static_cast<size_t>(PalInterlockedCompareExchange64 ((volatile int64_t *)target, (int64_t)value, (int64_t)expected));
+#else
+    return static_cast<size_t>(PalInterlockedCompareExchange ((volatile int32_t *)target, (int32_t)value, (int32_t)expected));
+#endif 
+}
+
+ep_char8_t *
+ep_rt_aot_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char8_t *expected, ep_char8_t *value) { 
+    STATIC_CONTRACT_NOTHROW;
+    return static_cast<ep_char8_t *>(PalInterlockedCompareExchangePointer ((void *volatile *)target, value, expected));
+}
+
+
+void
+ep_rt_aot_wait_event_alloc (
+    ep_rt_wait_event_handle_t *wait_event,
+    bool manual,
+    bool initial)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    EP_ASSERT (wait_event != NULL);
+    EP_ASSERT (wait_event->event == NULL);
+
+    wait_event->event = new (nothrow) CLREventStatic ();
+    if (wait_event->event) {
+        // NativeAOT has the NoThrow versions
+        if (manual)
+            wait_event->event->CreateManualEventNoThrow (initial);
+        else
+            wait_event->event->CreateAutoEventNoThrow (initial);
+    }
+}
+
+void
+ep_rt_aot_wait_event_free (ep_rt_wait_event_handle_t *wait_event)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (wait_event != NULL && wait_event->event != NULL) {
+        wait_event->event->CloseEvent ();
+        delete wait_event->event;
+        wait_event->event = NULL;
+    }
+}
+
+bool
+ep_rt_aot_wait_event_set (ep_rt_wait_event_handle_t *wait_event) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (wait_event != NULL && wait_event->event != NULL);
+
+    return wait_event->event->Set ();
+}
+
+int32_t
+ep_rt_aot_wait_event_wait (
+    ep_rt_wait_event_handle_t *wait_event,
+    uint32_t timeout,
+    bool alertable) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (wait_event != NULL && wait_event->event != NULL);
+
+    return wait_event->event->Wait (timeout, alertable);
+}
+
+bool
+ep_rt_aot_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+
+    if (wait_event == NULL || wait_event->event == NULL)
+        return false;
+
+    return wait_event->event->IsValid ();
+}
+
+/*
+ * Misc.
+ */
+
+int
+ep_rt_aot_get_last_error (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return PalGetLastError();
+}
+
+bool
+ep_rt_aot_thread_create (
+    void *thread_func,
+    void *params,
+    EventPipeThreadType thread_type,
+    void *id)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (thread_func != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Fill in the outgoing id if any callers ever need it
+    if (id)
+        *reinterpret_cast<DWORD*>(id) = 0xffffffff;
+
+    switch (thread_type)
+    {
+    default:
+        return false;
+
+    case EP_THREAD_TYPE_SERVER:
+        // Match CoreCLR and hardcode a null thread context in this case.
+        return PalStartEventPipeHelperThread(reinterpret_cast<BackgroundCallback>(thread_func), NULL);
+
+    case EP_THREAD_TYPE_SESSION:
+    case EP_THREAD_TYPE_SAMPLING:
+        ep_rt_thread_params_t* thread_params = new (nothrow) ep_rt_thread_params_t ();
+        if (!thread_params)
+            return false;
+
+        thread_params->thread_type = thread_type;
+        thread_params->thread_func = reinterpret_cast<ep_rt_thread_start_func>(thread_func);
+        thread_params->thread_params = params;
+        if (!PalStartEventPipeHelperThread(reinterpret_cast<BackgroundCallback>(ep_rt_thread_aot_start_session_or_sampling_thread), thread_params)) {
+            delete thread_params;
+            return false;
+        }
+
+        return true;
+    }
+}
+
+void
+ep_rt_aot_thread_sleep (uint64_t ns)
+{
+    STATIC_CONTRACT_NOTHROW;
+    PalSleep(static_cast<uint32_t>(ns/1000000));
+}
+
+uint32_t
+ep_rt_aot_current_process_get_id (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return static_cast<uint32_t>(GetCurrentProcessId ());
+}
+
+ep_rt_thread_id_t
+ep_rt_aot_current_thread_get_id (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef TARGET_UNIX
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: AOT doesn't have PAL_GetCurrentOSThreadId, as CoreCLR does.
+    // PalDebugBreak();    
+    return static_cast<ep_rt_thread_id_t>(0);
+#else
+    return static_cast<ep_rt_thread_id_t>(::GetCurrentThreadId ());
+#endif
+}
+
+int64_t
+ep_rt_aot_perf_counter_query (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (int64_t)PalQueryPerformanceCounter();
+}
+
+int64_t
+ep_rt_aot_perf_frequency_query (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (int64_t)PalQueryPerformanceFrequency();
+}
+
+int64_t
+ep_rt_aot_system_timestamp_get (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    FILETIME value;
+    GetSystemTimeAsFileTime (&value);
+    return static_cast<int64_t>(((static_cast<uint64_t>(value.dwHighDateTime)) << 32) | static_cast<uint64_t>(value.dwLowDateTime));
+}
+
+uint8_t *
+ep_rt_aot_valloc0 (size_t buffer_size)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return reinterpret_cast<uint8_t *>(PalVirtualAlloc (NULL, buffer_size, MEM_COMMIT, PAGE_READWRITE));
+}
+
+void
+ep_rt_aot_vfree (
+    uint8_t *buffer,
+    size_t buffer_size)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (buffer)
+        PalVirtualFree (buffer, 0, MEM_RELEASE);
+}
+
+void
+ep_rt_aot_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    spin_lock->lock = new (nothrow) SpinLock ();
+}
+
+void
+ep_rt_aot_spin_lock_free (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (spin_lock && spin_lock->lock) {
+        delete spin_lock->lock;
+        spin_lock->lock = NULL;
+    }
+}
+
+size_t
+ep_rt_aot_utf16_string_len (const ep_char16_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (str != NULL);
+
+    return wcslen (reinterpret_cast<LPCWSTR>(str));
+}
+
+uint32_t
+ep_rt_aot_volatile_load_uint32_t (const volatile uint32_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoad<uint32_t> ((const uint32_t *)ptr);
+}
+
+uint32_t
+ep_rt_aot_volatile_load_uint32_t_without_barrier (const volatile uint32_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoadWithoutBarrier<uint32_t> ((const uint32_t *)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_uint32_t (
+    volatile uint32_t *ptr,
+    uint32_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStore<uint32_t> ((uint32_t *)ptr, value);
+}
+
+void
+ep_rt_aot_volatile_store_uint32_t_without_barrier (
+    volatile uint32_t *ptr,
+    uint32_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStoreWithoutBarrier<uint32_t>((uint32_t *)ptr, value);
+}
+
+uint64_t
+ep_rt_aot_volatile_load_uint64_t (const volatile uint64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoad<uint64_t> ((const uint64_t *)ptr);
+}
+
+uint64_t
+ep_rt_aot_volatile_load_uint64_t_without_barrier (const volatile uint64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoadWithoutBarrier<uint64_t> ((const uint64_t *)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_uint64_t (
+    volatile uint64_t *ptr,
+    uint64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStore<uint64_t> ((uint64_t *)ptr, value);
+}
+
+void
+ep_rt_aot_volatile_store_uint64_t_without_barrier (
+    volatile uint64_t *ptr,
+    uint64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStoreWithoutBarrier<uint64_t> ((uint64_t *)ptr, value);
+}
+
+int64_t
+ep_rt_aot_volatile_load_int64_t (const volatile int64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoad<int64_t> ((int64_t *)ptr);
+}
+
+int64_t
+ep_rt_aot_volatile_load_int64_t_without_barrier (const volatile int64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoadWithoutBarrier<int64_t> ((int64_t *)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_int64_t (
+    volatile int64_t *ptr,
+    int64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStore<int64_t> ((int64_t *)ptr, value);
+}
+
+void
+ep_rt_aot_volatile_store_int64_t_without_barrier (
+    volatile int64_t *ptr,
+    int64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStoreWithoutBarrier<int64_t> ((int64_t *)ptr, value);
+}
+
+void *
+ep_rt_aot_volatile_load_ptr (volatile void **ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoad<void *> ((void **)ptr);
+}
+
+void *
+ep_rt_aot_volatile_load_ptr_without_barrier (volatile void **ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return VolatileLoadWithoutBarrier<void *> ((void **)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_ptr (
+    volatile void **ptr,
+    void *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStore<void *> ((void **)ptr, value);
+}
+
+void
+ep_rt_aot_volatile_store_ptr_without_barrier (
+    volatile void **ptr,
+    void *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    VolatileStoreWithoutBarrier<void *> ((void **)ptr, value);
+}
+
+#endif /* ENABLE_PERFTRACING */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h
new file mode 100644 (file)
index 0000000..5c6f8ab
--- /dev/null
@@ -0,0 +1,3145 @@
+// Implementation of ep-rt.h targeting CoreCLR runtime.
+#ifndef __EVENTPIPE_RT_AOT_H__
+#define __EVENTPIPE_RT_AOT_H__
+
+#include <ctype.h>  // For isspace
+
+#include <eventpipe/ep-rt-config.h>
+#ifdef ENABLE_PERFTRACING
+#include <eventpipe/ep-thread.h>
+#include <eventpipe/ep-types.h>
+#include <eventpipe/ep-provider.h>
+#include <eventpipe/ep-session-provider.h>
+
+#include "rhassert.h"
+
+#ifdef TARGET_UNIX
+#define sprintf_s snprintf
+#define _stricmp strcasecmp
+#define INFINITE            0xFFFFFFFF  // Infinite timeout
+#endif
+
+#define STATIC_CONTRACT_NOTHROW
+
+#undef EP_INFINITE_WAIT
+#define EP_INFINITE_WAIT INFINITE
+
+#undef EP_GCX_PREEMP_ENTER
+#define EP_GCX_PREEMP_ENTER { //GCX_PREEMP();
+
+#undef EP_GCX_PREEMP_EXIT
+#define EP_GCX_PREEMP_EXIT }
+
+#undef EP_ALWAYS_INLINE
+#define EP_ALWAYS_INLINE
+
+#undef EP_NEVER_INLINE
+#define EP_NEVER_INLINE
+
+#undef EP_ALIGN_UP
+#define EP_ALIGN_UP(val,align) _rt_aot_align_up(val,align)
+
+// shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+// TODO: The NativeAOT ALIGN_UP is defined in a tangled manner that generates linker errors if
+// it is used here; instead, define a version tailored to the existing usage in the shared
+// EventPipe code.
+static inline uint8_t* _rt_aot_align_up(uint8_t* val, uintptr_t alignment)
+{
+    // alignment must be a power of 2 for this implementation to work (need modulo otherwise)
+    EP_ASSERT( 0 == (alignment & (alignment - 1)) );
+    uintptr_t rawVal = reinterpret_cast<uintptr_t>(val);
+    uintptr_t result = (rawVal + (alignment - 1)) & ~(alignment - 1);
+    EP_ASSERT( result >= rawVal );      // check for overflow
+    return reinterpret_cast<uint8_t*>(result);
+}
+
+#ifndef EP_RT_BUILD_TYPE_FUNC_NAME
+#define EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, type_name, func_name) \
+prefix_name ## _rt_ ## type_name ## _ ## func_name
+#endif
+
+template<typename LIST_TYPE>
+static
+inline
+void
+_rt_aot_list_alloc (LIST_TYPE *list) {
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL);
+
+    list->list = new (nothrow) typename LIST_TYPE::list_type_t ();
+}
+
+template<typename LIST_TYPE>
+static
+inline
+void
+_rt_aot_list_free (
+    LIST_TYPE *list,
+    void (*callback)(void *))
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL);
+
+    if (list->list) {
+        while (!list->list->IsEmpty ()) {
+                typename LIST_TYPE::element_type_t *current = list->list->RemoveHead ();
+                if (callback)
+                    callback (reinterpret_cast<void *>(current->GetValue ()));
+                delete current;
+        }
+        delete list->list;
+    }
+    list->list = NULL;
+}
+
+template<typename LIST_TYPE>
+static
+inline
+void
+_rt_aot_list_clear (
+    LIST_TYPE *list,
+    void (*callback)(void *))
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL);
+
+    while (!list->list->IsEmpty ()) {
+        typename LIST_TYPE::element_type_t *current = list->list->RemoveHead ();
+        if (callback)
+                callback (reinterpret_cast<void *>(current->GetValue ()));
+        delete current;
+    }
+}
+
+template<typename LIST_TYPE, typename LIST_ITEM>
+static
+inline
+bool
+_rt_aot_list_append (
+    LIST_TYPE *list,
+    LIST_ITEM item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL);
+
+    typename LIST_TYPE::element_type_t *node = new (nothrow) typename LIST_TYPE::element_type_t (item);
+    if (node)
+        list->list->InsertTail (node);
+    return (node != NULL);
+}
+
+template<typename LIST_TYPE, typename LIST_ITEM, typename CONST_LIST_ITEM = LIST_ITEM>
+static
+inline
+void
+_rt_aot_list_remove (
+    LIST_TYPE *list,
+    CONST_LIST_ITEM item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL);
+
+    typename LIST_TYPE::element_type_t *current = list->list->GetHead ();
+    while (current) {
+        if (current->GetValue () == item) {
+            if (list->list->FindAndRemove (current))
+                    delete current;
+            break;
+        }
+        current = list->list->GetNext (current);
+    }
+}
+
+template<typename LIST_TYPE, typename LIST_ITEM, typename CONST_LIST_TYPE = const LIST_TYPE, typename CONST_LIST_ITEM = const LIST_ITEM>
+static
+inline
+bool
+_rt_aot_list_find (
+    CONST_LIST_TYPE *list,
+    CONST_LIST_ITEM item_to_find,
+    LIST_ITEM *found_item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL);
+    EP_ASSERT (found_item != NULL);
+
+    bool found = false;
+    typename LIST_TYPE::element_type_t *current = list->list->GetHead ();
+    while (current) {
+        if (current->GetValue () == item_to_find) {
+            *found_item = current->GetValue ();
+            found = true;
+            break;
+        }
+        current = list->list->GetNext (current);
+    }
+    return found;
+}
+
+template<typename LIST_TYPE, typename CONST_LIST_TYPE = const LIST_TYPE>
+static
+inline
+bool
+_rt_aot_list_is_empty (CONST_LIST_TYPE *list)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL);
+
+    return (list->list == NULL || list->list->IsEmpty ());
+}
+
+template<typename LIST_TYPE, typename CONST_LIST_TYPE = const LIST_TYPE>
+static
+inline
+bool
+_rt_aot_list_is_valid (CONST_LIST_TYPE *list)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (list != NULL && list->list != NULL);
+}
+
+template<typename LIST_TYPE, typename ITERATOR_TYPE, typename CONST_LIST_TYPE = const LIST_TYPE>
+static
+inline
+ITERATOR_TYPE
+_rt_aot_list_iterator_begin (CONST_LIST_TYPE *list)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL);
+
+    return list->list->begin ();
+}
+
+template<typename LIST_TYPE, typename ITERATOR_TYPE, typename CONST_LIST_TYPE = const LIST_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+bool
+_rt_aot_list_iterator_end (
+    CONST_LIST_TYPE *list,
+    CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (list != NULL && list->list != NULL && iterator != NULL);
+
+    return (*iterator == list->list->end ());
+}
+
+template<typename ITERATOR_TYPE>
+static
+inline
+void
+_rt_aot_list_iterator_next (ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL);
+
+    (*iterator)++;
+}
+
+template<typename ITERATOR_TYPE, typename ITEM_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+ITEM_TYPE
+_rt_aot_list_iterator_value (CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL);
+
+    return const_cast<ITERATOR_TYPE *>(iterator)->operator*();
+}
+
+template<typename QUEUE_TYPE>
+static
+inline
+void
+_rt_aot_queue_alloc (QUEUE_TYPE *queue)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL);
+
+    queue->queue = new (nothrow) typename QUEUE_TYPE::queue_type_t ();
+}
+
+template<typename QUEUE_TYPE>
+static
+inline
+void
+_rt_aot_queue_free (QUEUE_TYPE *queue)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL);
+
+    if (queue->queue)
+        delete queue->queue;
+    queue->queue = NULL;
+}
+
+template<typename QUEUE_TYPE, typename ITEM_TYPE>
+static
+inline
+bool
+_rt_aot_queue_pop_head (
+    QUEUE_TYPE *queue,
+    ITEM_TYPE *item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL && queue->queue != NULL && item != NULL);
+
+    bool found = true;
+    typename QUEUE_TYPE::element_type_t *node = queue->queue->RemoveHead ();
+    if (node) {
+        *item = node->m_Value;
+        delete node;
+    } else {
+        *item = NULL;
+        found = false;
+    }
+    return found;
+}
+
+template<typename QUEUE_TYPE, typename ITEM_TYPE>
+static
+inline
+bool
+_rt_aot_queue_push_head (
+    QUEUE_TYPE *queue,
+    ITEM_TYPE item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL && queue->queue != NULL);
+
+    typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item);
+    if (node)
+        queue->queue->InsertHead (node);
+    return (node != NULL);
+}
+
+template<typename QUEUE_TYPE, typename ITEM_TYPE>
+static
+inline
+bool
+_rt_aot_queue_push_tail (
+    QUEUE_TYPE *queue,
+    ITEM_TYPE item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL && queue->queue != NULL);
+
+    typename QUEUE_TYPE::element_type_t *node = new (nothrow) typename QUEUE_TYPE::element_type_t (item);
+    if (node)
+        queue->queue->InsertTail (node);
+    return (node != NULL);
+}
+
+template<typename QUEUE_TYPE, typename CONST_QUEUE_TYPE = const QUEUE_TYPE>
+static
+inline
+bool
+_rt_aot_queue_is_empty (CONST_QUEUE_TYPE *queue)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (queue != NULL && queue->queue != NULL);
+
+    return (queue->queue != NULL && queue->queue->IsEmpty ());
+}
+
+template<typename QUEUE_TYPE, typename CONST_QUEUE_TYPE = const QUEUE_TYPE>
+static
+inline
+bool
+_rt_aot_queue_is_valid (CONST_QUEUE_TYPE *queue)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (queue != NULL && queue->queue != NULL);
+}
+
+template<typename ARRAY_TYPE>
+static
+inline
+void
+_rt_aot_array_alloc (ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL);
+
+    ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t ();
+}
+
+template<typename ARRAY_TYPE>
+static
+inline
+void
+_rt_aot_array_alloc_capacity (
+    ARRAY_TYPE *ep_array,
+    size_t capacity)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL);
+
+    ep_array->array = new (nothrow) typename ARRAY_TYPE::array_type_t ();
+    if (ep_array->array)
+        ep_array->array->AllocNoThrow (capacity);
+}
+
+template<typename ARRAY_TYPE>
+static
+inline
+void
+_rt_aot_array_init_capacity (
+    ARRAY_TYPE *ep_array,
+    size_t capacity)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL);
+
+    if (ep_array->array)
+        ep_array->array->AllocNoThrow (capacity);
+}
+
+template<typename ARRAY_TYPE>
+static
+inline
+void
+_rt_aot_array_free (ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL);
+
+    if (ep_array->array) {
+        delete ep_array->array;
+        ep_array->array = NULL;
+    }
+}
+
+template<typename ARRAY_TYPE, typename ITEM_TYPE>
+static
+inline
+bool
+_rt_aot_array_append (
+    ARRAY_TYPE *ep_array,
+    ITEM_TYPE item)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    return ep_array->array->PushNoThrow (item);
+}
+
+template<typename ARRAY_TYPE, typename ITEM_TYPE>
+static
+inline
+void
+_rt_aot_array_clear (ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    while (ep_array->array->Size () > 0)
+        ITEM_TYPE item = ep_array->array->Pop ();
+    ep_array->array->Shrink ();
+}
+
+template<typename ARRAY_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE>
+static
+inline
+size_t
+_rt_aot_array_size (CONST_ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    return ep_array->array->Size ();
+}
+
+template<typename ARRAY_TYPE, typename ITEM_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE>
+static
+inline
+ITEM_TYPE *
+_rt_aot_array_data (CONST_ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    return ep_array->array->Ptr ();
+}
+
+template<typename ARRAY_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE>
+static
+inline
+bool
+_rt_aot_array_is_valid (CONST_ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (ep_array->array != NULL);
+}
+
+template<typename ARRAY_TYPE, typename ITERATOR_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE>
+static
+inline
+ITERATOR_TYPE
+_rt_aot_array_iterator_begin (CONST_ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    ITERATOR_TYPE temp;
+    temp.array = ep_array->array;
+    temp.index = 0;
+    return temp;
+}
+
+template<typename ARRAY_TYPE, typename ITERATOR_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+bool
+_rt_aot_array_iterator_end (
+    CONST_ARRAY_TYPE *ep_array,
+    CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL);
+
+    return (iterator->index >= static_cast<size_t>(iterator->array->Size ()));
+}
+
+template<typename ITERATOR_TYPE>
+static
+inline
+void
+_rt_aot_array_iterator_next (ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL);
+
+    iterator->index++;
+}
+
+template<typename ITERATOR_TYPE, typename ITEM_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+ITEM_TYPE
+_rt_aot_array_iterator_value (const CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL && iterator->array != NULL);
+    EP_ASSERT (iterator->index < static_cast<size_t>(iterator->array->Size ()));
+
+    return iterator->array->operator[] (iterator->index);
+}
+
+template<typename ARRAY_TYPE, typename ITERATOR_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE>
+static
+inline
+ITERATOR_TYPE
+_rt_aot_array_reverse_iterator_begin (CONST_ARRAY_TYPE *ep_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && ep_array->array != NULL);
+
+    ITERATOR_TYPE temp;
+    temp.array = ep_array->array;
+    temp.index = static_cast<size_t>(ep_array->array->Size ());
+    return temp;
+}
+
+template<typename ARRAY_TYPE, typename ITERATOR_TYPE, typename CONST_ARRAY_TYPE = const ARRAY_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+bool
+_rt_aot_array_reverse_iterator_end (
+    CONST_ARRAY_TYPE *ep_array,
+    CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_array != NULL && iterator != NULL && iterator->array != NULL);
+
+    return (iterator->index == 0);
+}
+
+template<typename ITERATOR_TYPE>
+static
+inline
+void
+_rt_aot_array_reverse_iterator_next (ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL);
+
+    iterator->index--;
+}
+
+template<typename ITERATOR_TYPE, typename ITEM_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+ITEM_TYPE
+_rt_aot_array_reverse_iterator_value (CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (iterator != NULL && iterator->array != NULL);
+    EP_ASSERT (iterator->index > 0);
+
+    return iterator->array->operator[] (iterator->index - 1);
+}
+
+template<typename HASH_MAP_TYPE>
+static
+inline
+void
+_rt_aot_hash_map_alloc (
+    HASH_MAP_TYPE *hash_map,
+    uint32_t (*hash_callback)(const void *),
+    bool (*eq_callback)(const void *, const void *),
+    void (*key_free_callback)(void *),
+    void (*value_free_callback)(void *))
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && key_free_callback == NULL);
+
+    hash_map->table = new (nothrow) typename HASH_MAP_TYPE::table_type_t ();
+    hash_map->callbacks.key_free_func = key_free_callback;
+    hash_map->callbacks.value_free_func = value_free_callback;
+}
+
+template<typename HASH_MAP_TYPE>
+static
+inline
+void
+_rt_aot_hash_map_free (HASH_MAP_TYPE *hash_map)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL);
+
+    if (hash_map->table) {
+        if (hash_map->callbacks.value_free_func) {
+            for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator)
+                    hash_map->callbacks.value_free_func (reinterpret_cast<void *>((ptrdiff_t)(iterator->Value ())));
+        }
+        delete hash_map->table;
+    }
+}
+
+template<typename HASH_MAP_TYPE, typename KEY_TYPE, typename VALUE_TYPE>
+static
+inline
+bool
+_rt_aot_hash_map_add (
+    HASH_MAP_TYPE *hash_map,
+    KEY_TYPE key,
+    VALUE_TYPE value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    return hash_map->table->Add (typename HASH_MAP_TYPE::table_type_t::element_t (key, value));
+}
+
+template<typename HASH_MAP_TYPE, typename KEY_TYPE, typename VALUE_TYPE>
+static
+inline
+bool
+_rt_aot_hash_map_add_or_replace (
+    HASH_MAP_TYPE *hash_map,
+    KEY_TYPE key,
+    VALUE_TYPE value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    return hash_map->table->AddOrReplaceNoThrow (typename HASH_MAP_TYPE::table_type_t::element_t (key, value));
+}
+
+template<typename HASH_MAP_TYPE>
+static
+inline
+void
+_rt_aot_hash_map_remove_all (HASH_MAP_TYPE *hash_map)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    if (hash_map->callbacks.value_free_func) {
+        for (typename HASH_MAP_TYPE::table_type_t::Iterator iterator = hash_map->table->Begin (); iterator != hash_map->table->End (); ++iterator)
+            hash_map->callbacks.value_free_func (reinterpret_cast<void *>((ptrdiff_t)(iterator->Value ())));
+    }
+    hash_map->table->RemoveAll ();
+}
+
+template<typename HASH_MAP_TYPE, typename KEY_TYPE, typename VALUE_TYPE, typename CONST_HASH_MAP_TYPE = const HASH_MAP_TYPE, typename CONST_KEY_TYPE = const KEY_TYPE>
+static
+inline
+bool
+_rt_aot_hash_map_lookup (
+    CONST_HASH_MAP_TYPE *hash_map,
+    CONST_KEY_TYPE key,
+    VALUE_TYPE *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    const typename HASH_MAP_TYPE::table_type_t::element_t *ret = hash_map->table->LookupPtr ((KEY_TYPE)key);
+    if (ret == NULL)
+        return false;
+    *value = ret->Value ();
+    return true;
+}
+
+template<typename HASH_MAP_TYPE, typename CONST_HASH_MAP_TYPE = const HASH_MAP_TYPE>
+static
+inline
+uint32_t
+_rt_aot_hash_map_count (CONST_HASH_MAP_TYPE *hash_map)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    return hash_map->table->GetCount ();
+}
+
+template<typename HASH_MAP_TYPE, typename CONST_HASH_MAP_TYPE = const HASH_MAP_TYPE>
+static
+inline
+bool
+_rt_aot_hash_map_is_valid (CONST_HASH_MAP_TYPE *hash_map)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+
+    return (hash_map != NULL && hash_map->table != NULL);
+}
+
+template<typename HASH_MAP_TYPE, typename KEY_TYPE, typename CONST_KEY_TYPE = const KEY_TYPE>
+static
+inline
+void
+_rt_aot_hash_map_remove (
+    HASH_MAP_TYPE *hash_map,
+    CONST_KEY_TYPE key)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    const typename HASH_MAP_TYPE::table_type_t::element_t *ret = NULL;
+    if (hash_map->callbacks.value_free_func)
+        ret = hash_map->table->LookupPtr ((KEY_TYPE)key);
+    hash_map->table->Remove ((KEY_TYPE)key);
+    if (ret)
+        hash_map->callbacks.value_free_func (reinterpret_cast<void *>(static_cast<ptrdiff_t>(ret->Value ())));
+}
+
+template<typename HASH_MAP_TYPE, typename ITERATOR_TYPE, typename CONST_HASH_MAP_TYPE = const HASH_MAP_TYPE>
+static
+inline
+ITERATOR_TYPE
+_rt_aot_hash_map_iterator_begin (CONST_HASH_MAP_TYPE *hash_map)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL);
+
+    return hash_map->table->Begin ();
+}
+
+template<typename HASH_MAP_TYPE, typename ITERATOR_TYPE, typename CONST_HASH_MAP_TYPE = const HASH_MAP_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+bool
+_rt_aot_hash_map_iterator_end (
+    CONST_HASH_MAP_TYPE *hash_map,
+    CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (hash_map != NULL && hash_map->table != NULL && iterator != NULL);
+
+    return (hash_map->table->End () == *iterator);
+}
+
+template<typename HASH_MAP_TYPE, typename ITERATOR_TYPE>
+static
+inline
+void
+_rt_aot_hash_map_iterator_next (ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (iterator != NULL);
+
+    (*iterator)++;
+}
+
+template<typename HASH_MAP_TYPE, typename ITERATOR_TYPE, typename KEY_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+KEY_TYPE
+_rt_aot_hash_map_iterator_key (CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (iterator != NULL);
+
+    return (*iterator)->Key ();
+}
+
+template<typename HASH_MAP_TYPE, typename ITERATOR_TYPE, typename VALUE_TYPE, typename CONST_ITERATOR_TYPE = const ITERATOR_TYPE>
+static
+inline
+VALUE_TYPE
+_rt_aot_hash_map_iterator_value (CONST_ITERATOR_TYPE *iterator)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (HASH_MAP_TYPE::table_type_t::s_NoThrow);
+    EP_ASSERT (iterator != NULL);
+
+    return (*iterator)->Value ();
+}
+
+#define EP_RT_DEFINE_LIST_PREFIX(prefix_name, list_name, list_type, item_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, alloc) (list_type *list) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_list_alloc<list_type>(list); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, free) (list_type *list, void (*callback)(void *)) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_list_free<list_type>(list, callback); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, clear) (list_type *list, void (*callback)(void *)) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_list_clear<list_type>(list, callback); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, append) (list_type *list, item_type item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_append<list_type, item_type>(list, item); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, remove) (list_type *list, const item_type item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_list_remove<list_type, item_type>(list, item); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, find) (const list_type *list, const item_type item_to_find, item_type *found_item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_find<list_type, item_type>(list, item_to_find, found_item); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_empty) (const list_type *list) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_is_empty<list_type>(list); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, is_valid) (const list_type *list) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_is_valid<list_type>(list); \
+    }
+
+#undef EP_RT_DEFINE_LIST
+#define EP_RT_DEFINE_LIST(list_name, list_type, item_type) \
+    EP_RT_DEFINE_LIST_PREFIX(ep, list_name, list_type, item_type)
+
+#define EP_RT_DEFINE_LIST_ITERATOR_PREFIX(prefix_name, list_name, list_type, iterator_type, item_type) \
+    static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_begin) (const list_type *list) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_iterator_begin<list_type, iterator_type>(list); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_end) (const list_type *list, const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_iterator_end<list_type, iterator_type>(list, iterator); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_next) (iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_list_iterator_next<iterator_type>(iterator); \
+    } \
+    static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, list_name, iterator_value) (const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_list_iterator_value<iterator_type, item_type>(iterator); \
+    }
+
+#undef EP_RT_DEFINE_LIST_ITERATOR
+#define EP_RT_DEFINE_LIST_ITERATOR(list_name, list_type, iterator_type, item_type) \
+    EP_RT_DEFINE_LIST_ITERATOR_PREFIX(ep, list_name, list_type, iterator_type, item_type)
+
+#define EP_RT_DEFINE_QUEUE_PREFIX(prefix_name, queue_name, queue_type, item_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, alloc) (queue_type *queue) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_queue_alloc<queue_type>(queue); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, free) (queue_type *queue) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_queue_free<queue_type>(queue); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, pop_head) (queue_type *queue, item_type *item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_queue_pop_head<queue_type, item_type>(queue, item); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_head) (queue_type *queue, item_type item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_queue_push_head<queue_type, item_type>(queue, item); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, push_tail) (queue_type *queue, item_type item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_queue_push_tail<queue_type, item_type>(queue, item); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_empty) (const queue_type *queue) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_queue_is_empty<queue_type>(queue); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, queue_name, is_valid) (const queue_type *queue) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_queue_is_valid<queue_type>(queue); \
+    }
+
+#undef EP_RT_DEFINE_QUEUE
+#define EP_RT_DEFINE_QUEUE(queue_name, queue_type, item_type) \
+    EP_RT_DEFINE_QUEUE_PREFIX(ep, queue_name, queue_type, item_type)
+
+#define EP_RT_DEFINE_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc) (array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_alloc<array_type>(ep_array); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, alloc_capacity) (array_type *ep_array, size_t capacity) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_alloc_capacity<array_type>(ep_array, capacity); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, free) (array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_free<array_type>(ep_array); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, append) (array_type *ep_array, item_type item) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_append<array_type, item_type> (ep_array, item); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, clear) (array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_clear<array_type, item_type> (ep_array); \
+    } \
+    static inline size_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, size) (const array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_size<array_type> (ep_array); \
+    } \
+    static inline item_type * EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, data) (const array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_data<array_type, item_type> (ep_array); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, is_valid) (const array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_is_valid<array_type> (ep_array); \
+    }
+
+#define EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init) (array_type *ep_array) { \
+        STATIC_CONTRACT_NOTHROW; \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, init_capacity) (array_type *ep_array, size_t capacity) { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_init_capacity<array_type>(ep_array, capacity); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, fini) (array_type *ep_array) { \
+        STATIC_CONTRACT_NOTHROW; \
+    }
+
+#undef EP_RT_DEFINE_ARRAY
+#define EP_RT_DEFINE_ARRAY(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type)
+
+#undef EP_RT_DEFINE_LOCAL_ARRAY
+#define EP_RT_DEFINE_LOCAL_ARRAY(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_LOCAL_ARRAY_PREFIX(ep, array_name, array_type, iterator_type, item_type)
+
+#define EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, var_type) \
+    var_type::array_type_t _local_ ##var_name; \
+    var_type var_name; \
+    var_name.array = &_local_ ##var_name
+
+#define EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \
+    static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_begin) (const array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_iterator_begin<array_type, iterator_type> (ep_array); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_end) (const array_type *ep_array, const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_iterator_end<array_type, iterator_type> (ep_array, iterator); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_next) (iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_iterator_next<iterator_type> (iterator); \
+    } \
+    static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, iterator_value) (const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_iterator_value<iterator_type, item_type> (iterator); \
+    }
+
+#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(prefix_name, array_name, array_type, iterator_type, item_type) \
+    static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_begin) (const array_type *ep_array) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_reverse_iterator_begin<array_type, iterator_type> (ep_array); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_end) (const array_type *ep_array, const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_reverse_iterator_end<array_type, iterator_type> (ep_array, iterator); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_next) (iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_array_reverse_iterator_next<iterator_type> (iterator); \
+    } \
+    static inline item_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, array_name, reverse_iterator_value) (const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_array_reverse_iterator_value<iterator_type, item_type> (iterator); \
+    }
+
+#undef EP_RT_DEFINE_ARRAY_ITERATOR
+#define EP_RT_DEFINE_ARRAY_ITERATOR(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type)
+
+#undef EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR
+#define EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR(array_name, array_type, iterator_type, item_type) \
+    EP_RT_DEFINE_ARRAY_REVERSE_ITERATOR_PREFIX(ep, array_name, array_type, iterator_type, item_type)
+
+#define EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, alloc) (hash_map_type *hash_map, uint32_t (*hash_callback)(const void *), bool (*eq_callback)(const void *, const void *), void (*key_free_callback)(void *), void (*value_free_callback)(void *)) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_hash_map_alloc<hash_map_type>(hash_map, hash_callback, eq_callback, key_free_callback, value_free_callback); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, free) (hash_map_type *hash_map) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_hash_map_free<hash_map_type>(hash_map); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add) (hash_map_type *hash_map, key_type key, value_type value) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_add<hash_map_type, key_type, value_type>(hash_map, key, value); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove_all) (hash_map_type *hash_map) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_hash_map_remove_all<hash_map_type>(hash_map); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, lookup) (const hash_map_type *hash_map, const key_type key, value_type *value) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_lookup<hash_map_type, key_type, value_type>(hash_map, key, value); \
+    } \
+    static inline uint32_t EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, count) (const hash_map_type *hash_map) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_count<hash_map_type>(hash_map); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, is_valid) (const hash_map_type *hash_map) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_is_valid<hash_map_type>(hash_map); \
+    }
+
+#define EP_RT_DEFINE_HASH_MAP_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \
+    EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, add_or_replace) (hash_map_type *hash_map, key_type key, value_type value) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_add_or_replace<hash_map_type, key_type, value_type>(hash_map, key, value); \
+    } \
+
+#define EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \
+    EP_RT_DEFINE_HASH_MAP_BASE_PREFIX(prefix_name, hash_map_name, hash_map_type, key_type, value_type) \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, remove) (hash_map_type *hash_map, const key_type key) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_hash_map_remove<hash_map_type, key_type>(hash_map, key); \
+    }
+
+#undef EP_RT_DEFINE_HASH_MAP
+#define EP_RT_DEFINE_HASH_MAP(hash_map_name, hash_map_type, key_type, value_type) \
+    EP_RT_DEFINE_HASH_MAP_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type)
+
+#undef EP_RT_DEFINE_HASH_MAP_REMOVE
+#define EP_RT_DEFINE_HASH_MAP_REMOVE(hash_map_name, hash_map_type, key_type, value_type) \
+    EP_RT_DEFINE_HASH_MAP_REMOVE_PREFIX(ep, hash_map_name, hash_map_type, key_type, value_type)
+
+#define EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(prefix_name, hash_map_name, hash_map_type, iterator_type, key_type, value_type) \
+    static inline iterator_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_begin) (const hash_map_type *hash_map) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_iterator_begin<hash_map_type, iterator_type>(hash_map); \
+    } \
+    static inline bool EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_end) (const hash_map_type *hash_map, const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_iterator_end<hash_map_type, iterator_type>(hash_map, iterator); \
+    } \
+    static inline void EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_next) (iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        _rt_aot_hash_map_iterator_next<hash_map_type, iterator_type>(iterator); \
+    } \
+    static inline key_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_key) (const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_iterator_key<hash_map_type, iterator_type, key_type>(iterator); \
+    } \
+    static inline value_type EP_RT_BUILD_TYPE_FUNC_NAME(prefix_name, hash_map_name, iterator_value) (const iterator_type *iterator) \
+    { \
+        STATIC_CONTRACT_NOTHROW; \
+        return _rt_aot_hash_map_iterator_value<hash_map_type, iterator_type, value_type>(iterator); \
+    }
+
+#undef EP_RT_DEFINE_HASH_MAP_ITERATOR
+#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \
+    EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type)
+
+static
+inline
+ep_rt_lock_handle_t *
+ep_rt_aot_config_lock_get (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+    return nullptr;
+}
+
+static
+inline
+const ep_char8_t *
+ep_rt_entrypoint_assembly_name_get_utf8 (void)
+{ 
+    STATIC_CONTRACT_NOTHROW;
+
+    extern const ep_char8_t * ep_rt_aot_entrypoint_assembly_name_get_utf8 (void);
+    return ep_rt_aot_entrypoint_assembly_name_get_utf8();
+}
+
+static
+const ep_char8_t *
+ep_rt_runtime_version_get_utf8 (void) { 
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Find a way to use CoreCLR runtime_version.h here if a more exact version is needed
+    return reinterpret_cast<const ep_char8_t*>("8.0.0");
+}
+
+/*
+ * Little-Endian Conversion.
+ */
+
+static
+inline
+uint16_t
+ep_rt_val_uint16_t (uint16_t value)
+{
+    return value;
+}
+
+static
+inline
+uint32_t
+ep_rt_val_uint32_t (uint32_t value)
+{
+    return value;
+}
+
+static
+inline
+uint64_t
+ep_rt_val_uint64_t (uint64_t value)
+{
+    return value;
+}
+
+static
+inline
+int16_t
+ep_rt_val_int16_t (int16_t value)
+{
+    return value;
+}
+
+static
+inline
+int32_t
+ep_rt_val_int32_t (int32_t value)
+{
+    return value;
+}
+
+static
+inline
+int64_t
+ep_rt_val_int64_t (int64_t value)
+{
+    return value;
+}
+
+static
+inline
+uintptr_t
+ep_rt_val_uintptr_t (uintptr_t value)
+{
+    return value;
+}
+
+/*
+* Atomics.
+*/
+
+static
+inline
+uint32_t
+ep_rt_atomic_inc_uint32_t (volatile uint32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint32_t ep_rt_aot_atomic_inc_uint32_t (volatile uint32_t *value);
+    return ep_rt_aot_atomic_inc_uint32_t (value);
+}
+
+static
+inline
+uint32_t
+ep_rt_atomic_dec_uint32_t (volatile uint32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint32_t ep_rt_aot_atomic_dec_uint32_t (volatile uint32_t *value);
+    return ep_rt_aot_atomic_dec_uint32_t (value);
+}
+
+static
+inline
+int32_t
+ep_rt_atomic_inc_int32_t (volatile int32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int32_t ep_rt_aot_atomic_inc_int32_t (volatile int32_t *value);
+
+    return ep_rt_aot_atomic_inc_int32_t (value);
+}
+
+static
+inline
+int32_t
+ep_rt_atomic_dec_int32_t (volatile int32_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int32_t ep_rt_aot_atomic_dec_int32_t (volatile int32_t *value);
+    return ep_rt_aot_atomic_dec_int32_t (value);
+}
+
+static
+inline
+int64_t
+ep_rt_atomic_inc_int64_t (volatile int64_t *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    extern int64_t ep_rt_aot_atomic_inc_int64_t (volatile int64_t *value);
+    return ep_rt_aot_atomic_inc_int64_t (value);
+}
+
+static
+inline
+int64_t
+ep_rt_atomic_dec_int64_t (volatile int64_t *value) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+
+    extern int64_t ep_rt_aot_atomic_dec_int64_t (volatile int64_t *value);
+    return ep_rt_aot_atomic_dec_int64_t (value);
+}
+
+static
+inline
+size_t
+ep_rt_atomic_compare_exchange_size_t (volatile size_t *target, size_t expected, size_t value) 
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern size_t ep_rt_aot_atomic_compare_exchange_size_t (volatile size_t *target, size_t expected, size_t value);
+    return ep_rt_aot_atomic_compare_exchange_size_t (target, expected, value);
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char8_t *expected, ep_char8_t *value) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    extern ep_char8_t * ep_rt_aot_atomic_compare_exchange_utf8_string (ep_char8_t *volatile *target, ep_char8_t *expected, ep_char8_t *value);
+    return ep_rt_aot_atomic_compare_exchange_utf8_string (target, expected, value);
+}
+
+/*
+ * EventPipe.
+ */
+
+EP_RT_DEFINE_ARRAY (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID)
+EP_RT_DEFINE_ARRAY_ITERATOR (session_id_array, ep_rt_session_id_array_t, ep_rt_session_id_array_iterator_t, EventPipeSessionID)
+
+EP_RT_DEFINE_ARRAY (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *)
+EP_RT_DEFINE_ARRAY_ITERATOR (execution_checkpoint_array, ep_rt_execution_checkpoint_array_t, ep_rt_execution_checkpoint_array_iterator_t, EventPipeExecutionCheckpoint *)
+
+static
+void
+ep_rt_init (void) 
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+}
+
+static
+inline
+void
+ep_rt_init_finish (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+}
+
+static
+inline
+void
+ep_rt_shutdown (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+}
+
+static
+inline
+bool
+ep_rt_config_acquire (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+    return true;   
+}
+
+static
+inline
+bool
+ep_rt_config_release (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+    return true;
+}
+
+#ifdef EP_CHECKED_BUILD
+static
+inline
+void
+ep_rt_config_requires_lock_held (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+    return;
+}
+
+static
+inline
+void
+ep_rt_config_requires_lock_not_held (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT
+    return;
+}
+#endif
+
+static
+inline
+bool
+ep_rt_walk_managed_stack_for_thread (
+    ep_rt_thread_handle_t thread,
+    EventPipeStackContents *stack_contents)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern bool ep_rt_aot_walk_managed_stack_for_thread (ep_rt_thread_handle_t thread, EventPipeStackContents *stack_contents);
+    return ep_rt_aot_walk_managed_stack_for_thread (thread, stack_contents);
+}
+
+static
+inline
+bool
+ep_rt_method_get_simple_assembly_name (
+    ep_rt_method_desc_t *method,
+    ep_char8_t *name,
+    size_t name_len)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Design MethodDesc and method name services if/when needed
+    //PalDebugBreak();
+
+    return false;
+
+}
+
+static
+bool
+ep_rt_method_get_full_name (
+    ep_rt_method_desc_t *method,
+    ep_char8_t *name,
+    size_t name_len)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Design MethodDesc and method name services if/when needed
+    //PalDebugBreak();
+
+    return false;
+}
+
+static
+inline
+void
+ep_rt_provider_config_init (EventPipeProviderConfiguration *provider_config)
+{
+    STATIC_CONTRACT_NOTHROW;
+}
+
+// This function is auto-generated from /src/scripts/genEventPipe.py
+#ifdef TARGET_UNIX
+extern "C" void InitProvidersAndEvents ();
+#else
+extern void InitProvidersAndEvents ();
+#endif
+
+static
+void
+ep_rt_init_providers_and_events (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: auto-generated fn, no op for now
+    // InitProvidersAndEvents ();
+}
+
+static
+inline
+bool
+ep_rt_providers_validate_all_disabled (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_DOTNET_Context and MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_DOTNET_Context are not available in NativeAOT
+    return true;
+}
+
+static
+inline
+void
+ep_rt_prepare_provider_invoke_callback (EventPipeProviderCallbackData *provider_callback_data)
+{
+    STATIC_CONTRACT_NOTHROW;
+}
+
+static
+void
+ep_rt_provider_invoke_callback (
+    EventPipeCallback callback_func,
+    const uint8_t *source_id,
+    unsigned long is_enabled,
+    uint8_t level,
+    uint64_t match_any_keywords,
+    uint64_t match_all_keywords,
+    EventFilterDescriptor *filter_data,
+    void *callback_data)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (callback_func != NULL);
+
+    (*callback_func)(
+        source_id,
+        is_enabled,
+        level,
+        match_any_keywords,
+        match_all_keywords,
+        filter_data,
+        callback_data);
+}
+
+/*
+ * EventPipeBuffer.
+ */
+
+EP_RT_DEFINE_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *)
+EP_RT_DEFINE_LOCAL_ARRAY (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *)
+EP_RT_DEFINE_ARRAY_ITERATOR (buffer_array, ep_rt_buffer_array_t, ep_rt_buffer_array_iterator_t, EventPipeBuffer *)
+
+#undef EP_RT_DECLARE_LOCAL_BUFFER_ARRAY
+#define EP_RT_DECLARE_LOCAL_BUFFER_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_array_t)
+
+/*
+ * EventPipeBufferList.
+ */
+
+EP_RT_DEFINE_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *)
+EP_RT_DEFINE_LOCAL_ARRAY (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *)
+EP_RT_DEFINE_ARRAY_ITERATOR (buffer_list_array, ep_rt_buffer_list_array_t, ep_rt_buffer_list_array_iterator_t, EventPipeBufferList *)
+
+#undef EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY
+#define EP_RT_DECLARE_LOCAL_BUFFER_LIST_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_buffer_list_array_t)
+
+/*
+ * EventPipeEvent.
+ */
+
+EP_RT_DEFINE_LIST (event_list, ep_rt_event_list_t, EventPipeEvent *)
+EP_RT_DEFINE_LIST_ITERATOR (event_list, ep_rt_event_list_t, ep_rt_event_list_iterator_t, EventPipeEvent *)
+
+/*
+ * EventPipeFile.
+ */
+
+EP_RT_DEFINE_HASH_MAP_REMOVE(metadata_labels_hash, ep_rt_metadata_labels_hash_map_t, EventPipeEvent *, uint32_t)
+EP_RT_DEFINE_HASH_MAP(stack_hash, ep_rt_stack_hash_map_t, StackHashKey *, StackHashEntry *)
+EP_RT_DEFINE_HASH_MAP_ITERATOR(stack_hash, ep_rt_stack_hash_map_t, ep_rt_stack_hash_map_iterator_t, StackHashKey *, StackHashEntry *)
+
+/*
+ * EventPipeProvider.
+ */
+
+EP_RT_DEFINE_LIST (provider_list, ep_rt_provider_list_t, EventPipeProvider *)
+EP_RT_DEFINE_LIST_ITERATOR (provider_list, ep_rt_provider_list_t, ep_rt_provider_list_iterator_t, EventPipeProvider *)
+
+EP_RT_DEFINE_QUEUE (provider_callback_data_queue, ep_rt_provider_callback_data_queue_t, EventPipeProviderCallbackData *)
+
+static
+EventPipeProvider *
+ep_rt_provider_list_find_by_name (
+    const ep_rt_provider_list_t *list,
+    const ep_char8_t *name)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // The provider list should be non-NULL, but can be NULL on shutdown.
+    if (list) {
+        SList_EP<SListElem_EP<EventPipeProvider *>> *provider_list = list->list;
+        SListElem_EP<EventPipeProvider *> *element = provider_list->GetHead ();
+        while (element) {
+            EventPipeProvider *provider = element->GetValue ();
+            if (ep_rt_utf8_string_compare (ep_provider_get_provider_name (element->GetValue ()), name) == 0)
+                return provider;
+
+            element = provider_list->GetNext (element);
+        }
+    }
+
+    return NULL;
+}
+
+/*
+ * EventPipeProviderConfiguration.
+ */
+
+EP_RT_DEFINE_ARRAY (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration)
+EP_RT_DEFINE_ARRAY_ITERATOR (provider_config_array, ep_rt_provider_config_array_t, ep_rt_provider_config_array_iterator_t, EventPipeProviderConfiguration)
+
+static
+inline
+bool
+ep_rt_config_value_get_enable (void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EnableEventPipe) != 0
+    // If EventPipe environment variables are specified, parse them and start a session.
+    // TODO: Not start a session for now
+    return false;
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_config_value_get_config (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EventPipeConfig)
+    // PalDebugBreak();
+    return nullptr;
+//     return ep_rt_utf16_to_utf8_string (reinterpret_cast<ep_char16_t *>(value.GetValue ()), -1);
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_config_value_get_output_path (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EventPipeOutputPath)
+    //PalDebugBreak();
+    return nullptr;
+}
+
+static
+inline
+uint32_t
+ep_rt_config_value_get_circular_mb (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EventPipeCircularMB)
+    //PalDebugBreak();
+    return 0;
+}
+
+static
+inline
+bool
+ep_rt_config_value_get_output_streaming (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EventPipeOutputStreaming)
+    //PalDebugBreak();
+    return false;
+}
+
+/*
+ * EventPipeSampleProfiler.
+ */
+
+static
+inline
+void
+ep_rt_sample_profiler_write_sampling_event_for_threads (
+    ep_rt_thread_handle_t sampling_thread,
+    EventPipeEvent *sampling_event)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    extern void ep_rt_aot_sample_profiler_write_sampling_event_for_threads (ep_rt_thread_handle_t sampling_thread, EventPipeEvent *sampling_event);
+    ep_rt_aot_sample_profiler_write_sampling_event_for_threads (sampling_thread, sampling_event);
+}
+
+static
+inline
+void
+ep_rt_notify_profiler_provider_created (EventPipeProvider *provider)
+{
+    // Following mono's path of no-op
+}
+
+/*
+ * EventPipeSessionProvider.
+ */
+
+EP_RT_DEFINE_LIST (session_provider_list, ep_rt_session_provider_list_t, EventPipeSessionProvider *)
+EP_RT_DEFINE_LIST_ITERATOR (session_provider_list, ep_rt_session_provider_list_t, ep_rt_session_provider_list_iterator_t, EventPipeSessionProvider *)
+
+static
+EventPipeSessionProvider *
+ep_rt_session_provider_list_find_by_name (
+    const ep_rt_session_provider_list_t *list,
+    const ep_char8_t *name)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    SList_EP<SListElem_EP<EventPipeSessionProvider *>> *provider_list = list->list;
+    EventPipeSessionProvider *session_provider = NULL;
+    SListElem_EP<EventPipeSessionProvider *> *element = provider_list->GetHead ();
+    while (element) {
+        EventPipeSessionProvider *candidate = element->GetValue ();
+        if (ep_rt_utf8_string_compare (ep_session_provider_get_provider_name (candidate), name) == 0) {
+            session_provider = candidate;
+            break;
+        }
+        element = provider_list->GetNext (element);
+    }
+
+    return session_provider;
+}
+
+/*
+ * EventPipeSequencePoint.
+ */
+
+EP_RT_DEFINE_LIST (sequence_point_list, ep_rt_sequence_point_list_t, EventPipeSequencePoint *)
+EP_RT_DEFINE_LIST_ITERATOR (sequence_point_list, ep_rt_sequence_point_list_t, ep_rt_sequence_point_list_iterator_t, EventPipeSequencePoint *)
+
+/*
+ * EventPipeThread.
+ */
+
+EP_RT_DEFINE_LIST (thread_list, ep_rt_thread_list_t, EventPipeThread *)
+EP_RT_DEFINE_LIST_ITERATOR (thread_list, ep_rt_thread_list_t, ep_rt_thread_list_iterator_t, EventPipeThread *)
+
+EP_RT_DEFINE_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *)
+EP_RT_DEFINE_LOCAL_ARRAY (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *)
+EP_RT_DEFINE_ARRAY_ITERATOR (thread_array, ep_rt_thread_array_t, ep_rt_thread_array_iterator_t, EventPipeThread *)
+
+#undef EP_RT_DECLARE_LOCAL_THREAD_ARRAY
+#define EP_RT_DECLARE_LOCAL_THREAD_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_array_t)
+
+/*
+ * EventPipeThreadSessionState.
+ */
+
+EP_RT_DEFINE_LIST (thread_session_state_list, ep_rt_thread_session_state_list_t, EventPipeThreadSessionState *)
+EP_RT_DEFINE_LIST_ITERATOR (thread_session_state_list, ep_rt_thread_session_state_list_t, ep_rt_thread_session_state_list_iterator_t, EventPipeThreadSessionState *)
+
+EP_RT_DEFINE_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *)
+EP_RT_DEFINE_LOCAL_ARRAY (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *)
+EP_RT_DEFINE_ARRAY_ITERATOR (thread_session_state_array, ep_rt_thread_session_state_array_t, ep_rt_thread_session_state_array_iterator_t, EventPipeThreadSessionState *)
+
+#undef EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY
+#define EP_RT_DECLARE_LOCAL_THREAD_SESSION_STATE_ARRAY(var_name) \
+    EP_RT_DECLARE_LOCAL_ARRAY_VARIABLE(var_name, ep_rt_thread_session_state_array_t)
+
+/*
+ * Arrays.
+ */
+
+static
+inline
+uint8_t *
+ep_rt_byte_array_alloc (size_t len)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return new (nothrow) uint8_t [len];
+}
+
+static
+inline
+void
+ep_rt_byte_array_free (uint8_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (ptr)
+        delete [] ptr;
+}
+
+/*
+ * Event.
+ */
+
+static
+void
+ep_rt_wait_event_alloc (
+    ep_rt_wait_event_handle_t *wait_event,
+    bool manual,
+    bool initial)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    extern void ep_rt_aot_wait_event_alloc (
+    ep_rt_wait_event_handle_t *wait_event,
+    bool manual,
+    bool initial);
+    ep_rt_aot_wait_event_alloc(wait_event, manual, initial);
+}
+
+static
+inline
+void
+ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void ep_rt_aot_wait_event_free (ep_rt_wait_event_handle_t *wait_event);
+    ep_rt_aot_wait_event_free(wait_event);
+}
+
+static
+inline
+bool
+ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    extern bool ep_rt_aot_wait_event_set (ep_rt_wait_event_handle_t *wait_event);
+    return ep_rt_aot_wait_event_set (wait_event);
+}
+
+static
+int32_t
+ep_rt_wait_event_wait (
+    ep_rt_wait_event_handle_t *wait_event,
+    uint32_t timeout,
+    bool alertable) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    extern int32_t
+ep_rt_aot_wait_event_wait (
+    ep_rt_wait_event_handle_t *wait_event,
+    uint32_t timeout,
+    bool alertable);
+
+    return ep_rt_aot_wait_event_wait(wait_event, timeout, alertable);
+}
+
+static
+inline
+EventPipeWaitHandle
+ep_rt_wait_event_get_wait_handle (ep_rt_wait_event_handle_t *wait_event) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    // EP_ASSERT (wait_event != NULL && wait_event->event != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: NativeAOT CLREventStatic doesn't have GetHandleUNHOSTED
+    // PalDebugBreak();
+    return 0;
+}
+
+static
+inline
+bool
+ep_rt_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event) 
+{ 
+    STATIC_CONTRACT_NOTHROW;
+    extern bool
+    ep_rt_aot_wait_event_is_valid (ep_rt_wait_event_handle_t *wait_event);
+
+    return ep_rt_aot_wait_event_is_valid (wait_event);
+}
+
+/*
+ * Misc.
+ */
+
+static
+inline
+int
+ep_rt_get_last_error (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int
+    ep_rt_aot_get_last_error (void);
+    return ep_rt_aot_get_last_error ();
+}
+
+static
+inline
+bool
+ep_rt_process_detach (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    return false;
+}
+
+static
+inline
+bool
+ep_rt_process_shutdown (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    return false;
+}
+
+static
+inline
+void
+ep_rt_create_activity_id (
+    uint8_t *activity_id,
+    uint32_t activity_id_len)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (activity_id != NULL);
+    EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement a way to generate a real Guid
+    // CoCreateGuid (reinterpret_cast<GUID *>(activity_id));
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Using roughly Mono's implementation but Mono randomly generates this, hardcoding for now
+    uint8_t data1[] = {0x67,0xac,0x33,0xf1,0x8d,0xed,0x41,0x01,0xb4,0x26,0xc9,0xb7,0x94,0x35,0xf7,0x8a};
+    memcpy (activity_id, data1, EP_ACTIVITY_ID_SIZE);
+
+       const uint16_t version_mask = 0xF000;
+       const uint16_t random_guid_version = 0x4000;
+       const uint8_t clock_seq_hi_and_reserved_mask = 0xC0;
+       const uint8_t clock_seq_hi_and_reserved_value = 0x80;
+
+       // Modify bits indicating the type of the GUID
+       uint8_t *activity_id_c = activity_id + sizeof (uint32_t) + sizeof (uint16_t);
+       uint8_t *activity_id_d = activity_id + sizeof (uint32_t) + sizeof (uint16_t) + sizeof (uint16_t);
+
+       uint16_t c;
+       memcpy (&c, activity_id_c, sizeof (c));
+
+       uint8_t d;
+       memcpy (&d, activity_id_d, sizeof (d));
+
+       // time_hi_and_version
+       c = ((c & ~version_mask) | random_guid_version);
+       // clock_seq_hi_and_reserved
+       d = ((d & ~clock_seq_hi_and_reserved_mask) | clock_seq_hi_and_reserved_value);
+
+       memcpy (activity_id_c, &c, sizeof (c));
+       memcpy (activity_id_d, &d, sizeof (d));
+}
+
+static
+inline
+bool
+ep_rt_is_running (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Does NativeAot have the concept of EEStarted
+    // PalDebugBreak();
+
+    return false;
+}
+
+static
+inline
+void
+ep_rt_execute_rundown (ep_rt_execution_checkpoint_array_t *execution_checkpoints)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    //TODO: Write execution checkpoint rundown events.
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: EventPipe Configuration values - RhConfig?
+    // (CLRConfig::INTERNAL_EventPipeCircularMB)
+    // PalDebugBreak();
+}
+
+/*
+ * Objects.
+ */
+
+// STATIC_CONTRACT_NOTHROW
+#undef ep_rt_object_alloc
+#define ep_rt_object_alloc(obj_type) (new (nothrow) obj_type())
+
+// STATIC_CONTRACT_NOTHROW
+#undef ep_rt_object_array_alloc
+#define ep_rt_object_array_alloc(obj_type,size) (new (nothrow) obj_type [size]())
+
+// STATIC_CONTRACT_NOTHROW
+#undef ep_rt_object_array_free
+#define ep_rt_object_array_free(obj_ptr) do { if (obj_ptr) delete [] obj_ptr; } while(0)
+
+// STATIC_CONTRACT_NOTHROW
+#undef ep_rt_object_free
+#define ep_rt_object_free(obj_ptr) do { if (obj_ptr) delete obj_ptr; } while(0)
+
+/*
+ * PAL.
+ */
+
+#undef EP_RT_DEFINE_THREAD_FUNC
+#define EP_RT_DEFINE_THREAD_FUNC(name) static ep_rt_thread_start_func_return_t __stdcall name (void *data)
+
+EP_RT_DEFINE_THREAD_FUNC (ep_rt_thread_aot_start_session_or_sampling_thread)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    ep_rt_thread_params_t* thread_params = reinterpret_cast<ep_rt_thread_params_t *>(data);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed.
+    // The session and sampling threads both assert that the incoming thread handle is
+    // non-null, but do not necessarily rely on it otherwise; just pass a meaningless non-null
+    // value until testing shows that a meaningful value is needed.
+    thread_params->thread = reinterpret_cast<ep_rt_thread_handle_t>(1);
+
+    size_t result = thread_params->thread_func (thread_params);
+    delete thread_params;
+    return result;
+}
+
+static
+bool
+ep_rt_thread_create (
+    void *thread_func,
+    void *params,
+    EventPipeThreadType thread_type,
+    void *id)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern bool
+    ep_rt_aot_thread_create (
+    void *thread_func,
+    void *params,
+    EventPipeThreadType thread_type,
+    void *id);
+
+    return ep_rt_aot_thread_create(thread_func, params, thread_type, id);
+}
+
+static
+inline
+void
+ep_rt_set_server_name(void)
+{
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Need to set name for  the thread
+    // ::SetThreadName(GetCurrentThread(), W(".NET EventPipe"));
+}
+
+
+static
+inline
+void
+ep_rt_thread_sleep (uint64_t ns)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_thread_sleep (uint64_t ns);
+    ep_rt_aot_thread_sleep(ns);
+}
+
+static
+inline
+uint32_t
+ep_rt_current_process_get_id (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint32_t
+    ep_rt_aot_current_process_get_id (void);
+    return ep_rt_aot_current_process_get_id();
+}
+
+static
+inline
+uint32_t
+ep_rt_current_processor_get_number (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifndef TARGET_UNIX
+    extern uint32_t *_ep_rt_aot_proc_group_offsets;
+    if (_ep_rt_aot_proc_group_offsets) {
+        // PROCESSOR_NUMBER proc;
+        // GetCurrentProcessorNumberEx (&proc);
+        // return _ep_rt_aot_proc_group_offsets [proc.Group] + proc.Number;
+        // PalDebugBreak();
+    }
+#endif
+    return 0xFFFFFFFF;
+}
+
+static
+inline
+uint32_t
+ep_rt_processors_get_count (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+#ifdef _INC_WINDOWS
+    SYSTEM_INFO sys_info = {};
+    GetSystemInfo (&sys_info);
+    return static_cast<uint32_t>(sys_info.dwNumberOfProcessors);
+#else    
+    // PalDebugBreak();
+    return 0xffff;
+#endif
+}
+
+static
+inline
+ep_rt_thread_id_t
+ep_rt_current_thread_get_id (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern ep_rt_thread_id_t
+    ep_rt_aot_current_thread_get_id (void);
+    return ep_rt_aot_current_thread_get_id();
+}
+
+static
+inline
+int64_t
+ep_rt_perf_counter_query (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int64_t
+    ep_rt_aot_perf_counter_query (void);
+
+    return ep_rt_aot_perf_counter_query();
+}
+
+static
+inline
+int64_t
+ep_rt_perf_frequency_query (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int64_t
+    ep_rt_aot_perf_frequency_query (void);
+
+    return ep_rt_aot_perf_frequency_query();
+}
+
+static
+inline
+void
+ep_rt_system_time_get (EventPipeSystemTime *system_time)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+#ifdef _INC_WINDOWS
+    SYSTEMTIME value;
+    GetSystemTime (&value);
+
+    EP_ASSERT(system_time != NULL);
+    ep_system_time_set (
+       system_time,
+       value.wYear,
+       value.wMonth,
+       value.wDayOfWeek,
+       value.wDay,
+       value.wHour,
+       value.wMinute,
+       value.wSecond,
+       value.wMilliseconds);
+#else
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Get System time
+    // PalDebugBreak();
+#endif
+
+}
+
+static
+inline
+int64_t
+ep_rt_system_timestamp_get (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int64_t ep_rt_aot_system_timestamp_get (void);
+    return ep_rt_aot_system_timestamp_get();
+}
+
+static
+inline
+int32_t
+ep_rt_system_get_alloc_granularity (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // return static_cast<int32_t>(g_SystemInfo.dwAllocationGranularity);
+    return 0x10000;
+}
+
+static
+inline
+const ep_char8_t *
+ep_rt_os_command_line_get (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    //EP_UNREACHABLE ("Can not reach here");
+
+    return NULL;
+}
+
+static
+ep_rt_file_handle_t
+ep_rt_file_open_write (const ep_char8_t *path)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    ep_char16_t *path_utf16 = ep_rt_utf8_to_utf16le_string (path, -1);
+    ep_return_null_if_nok (path_utf16 != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Find out the way to open a file in native
+    // PalDebugBreak();
+
+    return 0;
+}
+
+static
+inline
+bool
+ep_rt_file_close (ep_rt_file_handle_t file_handle)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Find out the way to close a file in native
+    // PalDebugBreak();
+    return true;
+}
+
+static
+inline
+bool
+ep_rt_file_write (
+    ep_rt_file_handle_t file_handle,
+    const uint8_t *buffer,
+    uint32_t bytes_to_write,
+    uint32_t *bytes_written)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (buffer != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Find out the way to write to a file in native
+    // PalDebugBreak();
+    
+    return false;
+}
+
+static
+inline
+uint8_t *
+ep_rt_valloc0 (size_t buffer_size)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint8_t *
+    ep_rt_aot_valloc0 (size_t buffer_size);
+
+    return ep_rt_aot_valloc0(buffer_size);
+}
+
+static
+inline
+void
+ep_rt_vfree (
+    uint8_t *buffer,
+    size_t buffer_size)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_vfree (
+    uint8_t *buffer,
+    size_t buffer_size);
+
+    return ep_rt_aot_vfree(buffer, buffer_size);
+}
+
+static
+inline
+uint32_t
+ep_rt_temp_path_get (
+    ep_char8_t *buffer,
+    uint32_t buffer_len)
+{
+    STATIC_CONTRACT_NOTHROW;
+//    EP_UNREACHABLE ("Can not reach here");
+
+    return 0;
+}
+
+EP_RT_DEFINE_ARRAY (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *)
+EP_RT_DEFINE_ARRAY_ITERATOR (env_array_utf16, ep_rt_env_array_utf16_t, ep_rt_env_array_utf16_iterator_t, ep_char16_t *)
+
+static
+void
+ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (env_array != NULL);
+
+    // PalDebugBreak();
+}
+
+/*
+* Lock.
+*/
+
+static
+bool
+ep_rt_lock_acquire (ep_rt_lock_handle_t *lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    bool result = true;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT 
+
+    return result;
+}
+
+static
+bool
+ep_rt_lock_release (ep_rt_lock_handle_t *lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    bool result = true;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement EventPipe locking for NativeAOT 
+
+    return result;
+}
+
+#ifdef EP_CHECKED_BUILD
+static
+inline
+void
+ep_rt_lock_requires_lock_held (const ep_rt_lock_handle_t *lock)
+{
+
+    STATIC_CONTRACT_NOTHROW;
+    //EP_ASSERT (((ep_rt_lock_handle_t *)lock)->lock->OwnedByCurrentThread ());
+}
+
+static
+inline
+void
+ep_rt_lock_requires_lock_not_held (const ep_rt_lock_handle_t *lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    //EP_ASSERT (lock->lock == NULL || !((ep_rt_lock_handle_t *)lock)->lock->OwnedByCurrentThread ());
+}
+#endif
+
+/*
+* SpinLock.
+*/
+
+static
+void
+ep_rt_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock);
+    ep_rt_aot_spin_lock_alloc(spin_lock);
+}
+
+static
+inline
+void
+ep_rt_spin_lock_free (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_spin_lock_free (ep_rt_spin_lock_handle_t *spin_lock);
+    ep_rt_aot_spin_lock_free(spin_lock);
+}
+
+static
+inline
+bool
+ep_rt_spin_lock_acquire (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+//    EP_ASSERT (ep_rt_spin_lock_is_valid (spin_lock));
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement locking (maybe by making the manual Lock and Unlock functions public)
+    // SpinLock::Lock (*(spin_lock->lock));
+    return true;
+}
+
+static
+inline
+bool
+ep_rt_spin_lock_release (ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_rt_spin_lock_is_valid (spin_lock));
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement locking (maybe by making the manual Lock and Unlock functions public)
+    // SpinLock::Unlock (*(spin_lock->lock));
+    return true;
+}
+
+#ifdef EP_CHECKED_BUILD
+static
+inline
+void
+ep_rt_spin_lock_requires_lock_held (const ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (ep_rt_spin_lock_is_valid (spin_lock));
+
+}
+
+static
+inline
+void
+ep_rt_spin_lock_requires_lock_not_held (const ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+}
+#endif
+
+static
+inline
+bool
+ep_rt_spin_lock_is_valid (const ep_rt_spin_lock_handle_t *spin_lock)
+{
+    STATIC_CONTRACT_NOTHROW;
+    return (spin_lock != NULL && spin_lock->lock != NULL);
+}
+
+/*
+ * String.
+ */
+
+static
+inline
+int
+ep_rt_utf8_string_compare (
+    const ep_char8_t *str1,
+    const ep_char8_t *str2)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (str1 != NULL && str2 != NULL);
+
+    return strcmp (reinterpret_cast<const char *>(str1), reinterpret_cast<const char *>(str2));
+}
+
+static
+inline
+int
+ep_rt_utf8_string_compare_ignore_case (
+    const ep_char8_t *str1,
+    const ep_char8_t *str2)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (str1 != NULL && str2 != NULL);
+
+    return _stricmp (reinterpret_cast<const char *>(str1), reinterpret_cast<const char *>(str2));
+}
+
+static
+inline
+bool
+ep_rt_utf8_string_is_null_or_empty (const ep_char8_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (str == NULL)
+        return true;
+
+    while (*str) {
+        if (!isspace (*str))
+            return false;
+        str++;
+    }
+    return true;
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_utf8_string_dup (const ep_char8_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (!str)
+        return NULL;
+
+#ifdef TARGET_UNIX
+    return strdup (str);
+#else
+    return _strdup (str);
+#endif
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_utf8_string_dup_range (const ep_char8_t *str, const ep_char8_t *strEnd)
+{
+    ptrdiff_t byte_len = strEnd - str;
+    ep_char8_t *buffer = reinterpret_cast<ep_char8_t *>(malloc(byte_len + 1));
+    if (buffer != NULL)
+    {
+        memcpy (buffer, str, byte_len);
+        buffer [byte_len] = '\0';
+    }
+    return buffer;
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_utf8_string_strtok (
+    ep_char8_t *str,
+    const ep_char8_t *delimiter,
+    ep_char8_t **context)
+{
+    STATIC_CONTRACT_NOTHROW;
+#ifdef TARGET_UNIX
+    return strtok_r (str, delimiter, context);
+#else
+    return strtok_s (str, delimiter, context);
+#endif    
+}
+
+// STATIC_CONTRACT_NOTHROW
+#undef ep_rt_utf8_string_snprintf
+#define ep_rt_utf8_string_snprintf( \
+    str, \
+    str_len, \
+    format, ...) \
+sprintf_s (reinterpret_cast<char *>(str), static_cast<size_t>(str_len), reinterpret_cast<const char *>(format), __VA_ARGS__)
+
+static
+inline
+bool
+ep_rt_utf8_string_replace (
+    ep_char8_t **str,
+    const ep_char8_t *strSearch,
+    const ep_char8_t *strReplacement
+)
+{
+    STATIC_CONTRACT_NOTHROW;
+    if ((*str) == NULL)
+        return false;
+
+    ep_char8_t* strFound = strstr(*str, strSearch);
+    if (strFound != NULL)
+    {
+        size_t strSearchLen = strlen(strSearch);
+        size_t newStrSize = strlen(*str) + strlen(strReplacement) - strSearchLen + 1;
+        ep_char8_t *newStr =  reinterpret_cast<ep_char8_t *>(malloc(newStrSize));
+        if (newStr == NULL)
+        {
+            *str = NULL;
+            return false;
+        }
+        ep_rt_utf8_string_snprintf(newStr, newStrSize, "%.*s%s%s", (int)(strFound - (*str)), *str, strReplacement, strFound + strSearchLen);
+        ep_rt_utf8_string_free(*str);
+        *str = newStr;
+        return true;
+    }
+    return false;
+}
+
+static
+ep_char16_t *
+ep_rt_utf8_to_utf16le_string (
+    const ep_char8_t *str,
+    size_t len)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (!str)
+        return NULL;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implementation would just use strlen and malloc to make a new buffer, and would then copy the string chars one by one
+    size_t len_utf8 = strlen(str);        
+    if (len_utf8 == 0)
+        return NULL;
+
+    ep_char16_t *str_utf16 = reinterpret_cast<ep_char16_t *>(malloc ((len_utf8 + 1) * sizeof (ep_char16_t)));
+    if (!str_utf16)
+        return NULL;
+
+    for (size_t i = 0; i < len_utf8; i++)
+    {
+         str_utf16[i] = str[i];
+    }
+
+    str_utf16[len_utf8] = 0;
+    return str_utf16;
+}
+
+static
+inline
+ep_char16_t *
+ep_rt_utf16_string_dup (const ep_char16_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (!str)
+        return NULL;
+
+    size_t str_size = (ep_rt_utf16_string_len (str) + 1) * sizeof (ep_char16_t);
+    ep_char16_t *str_dup = reinterpret_cast<ep_char16_t *>(malloc (str_size));
+    if (str_dup)
+        memcpy (str_dup, str, str_size);
+    return str_dup;
+}
+
+static
+inline
+void
+ep_rt_utf8_string_free (ep_char8_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (str)
+        free (str);
+}
+
+static
+inline
+size_t
+ep_rt_utf16_string_len (const ep_char16_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern size_t
+    ep_rt_aot_utf16_string_len (const ep_char16_t *str);
+    return ep_rt_aot_utf16_string_len(str);
+}
+
+static
+ep_char8_t *
+ep_rt_utf16_to_utf8_string (
+    const ep_char16_t *str,
+    size_t len)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (!str)
+        return NULL;
+    
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Temp implementation that is the reverse of ep_rt_utf8_to_utf16le_string
+    size_t len_utf16 = len;
+    if(len_utf16 == -1)
+    {
+        len_utf16 = ep_rt_utf16_string_len (str);
+    }
+
+    ep_char8_t *str_utf8 = reinterpret_cast<ep_char8_t *>(malloc ((len_utf16 + 1) * sizeof (ep_char8_t)));
+    if (!str_utf8)
+        return NULL;
+
+    for (size_t i = 0; i < len_utf16; i++)
+    {
+         str_utf8[i] = (char)str[i];
+    }
+
+    str_utf8[len_utf16] = 0;
+    return str_utf8;
+}
+
+static
+inline
+ep_char8_t *
+ep_rt_utf16le_to_utf8_string (
+    const ep_char16_t *str,
+    size_t len)
+{
+    return ep_rt_utf16_to_utf8_string (str, len);
+}
+
+static
+inline
+void
+ep_rt_utf16_string_free (ep_char16_t *str)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    if (str)
+        free (str);
+}
+
+static
+inline
+const ep_char8_t *
+ep_rt_managed_command_line_get (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    //EP_UNREACHABLE ("Can not reach here");
+
+    return NULL;
+}
+
+static
+const ep_char8_t *
+ep_rt_diagnostics_command_line_get (void)
+{
+
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: revisit commandline for AOT
+    // return reinterpret_cast<const ep_char8_t *>(::GetCommandLineA());
+
+    extern ep_char8_t *volatile _ep_rt_aot_diagnostics_cmd_line;
+    ep_char8_t *old_cmd_line = _ep_rt_aot_diagnostics_cmd_line;
+    return _ep_rt_aot_diagnostics_cmd_line;
+}
+
+/*
+ * Thread.
+ */
+
+static
+inline
+EventPipeThreadHolder *
+thread_holder_alloc_func (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EventPipeThreadHolder *instance = ep_thread_holder_alloc (ep_thread_alloc());
+    if (instance)
+        ep_thread_register (ep_thread_holder_get_thread (instance));
+    return instance;
+}
+
+static
+inline
+void
+thread_holder_free_func (EventPipeThreadHolder * thread_holder)
+{
+    STATIC_CONTRACT_NOTHROW;
+    if (thread_holder) {
+        ep_thread_unregister (ep_thread_holder_get_thread (thread_holder));
+        ep_thread_holder_free (thread_holder);
+    }
+}
+
+class EventPipeAotThreadHolderTLS {
+public:
+    EventPipeAotThreadHolderTLS ()
+    {
+        STATIC_CONTRACT_NOTHROW;
+    }
+
+    ~EventPipeAotThreadHolderTLS ()
+    {
+        STATIC_CONTRACT_NOTHROW;
+
+        if (m_threadHolder) {
+            thread_holder_free_func (m_threadHolder);
+            m_threadHolder = NULL;
+        }
+    }
+
+    static inline EventPipeThreadHolder * getThreadHolder ()
+    {
+        STATIC_CONTRACT_NOTHROW;
+        return g_threadHolderTLS.m_threadHolder;
+    }
+
+    static inline EventPipeThreadHolder * createThreadHolder ()
+    {
+        STATIC_CONTRACT_NOTHROW;
+
+        if (g_threadHolderTLS.m_threadHolder) {
+            thread_holder_free_func (g_threadHolderTLS.m_threadHolder);
+            g_threadHolderTLS.m_threadHolder = NULL;
+        }
+        g_threadHolderTLS.m_threadHolder = thread_holder_alloc_func ();
+        return g_threadHolderTLS.m_threadHolder;
+    }
+
+private:
+    EventPipeThreadHolder *m_threadHolder;
+    static thread_local EventPipeAotThreadHolderTLS g_threadHolderTLS;
+};
+
+static
+void
+ep_rt_thread_setup (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // Thread* thread_handle = SetupThreadNoThrow ();
+    // EP_ASSERT (thread_handle != NULL);
+}
+
+static
+inline
+EventPipeThread *
+ep_rt_thread_get (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    EventPipeThreadHolder *thread_holder = EventPipeAotThreadHolderTLS::getThreadHolder ();
+    return thread_holder ? ep_thread_holder_get_thread (thread_holder) : NULL;
+}
+
+static
+inline
+EventPipeThread *
+ep_rt_thread_get_or_create (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+
+    EventPipeThreadHolder *thread_holder = EventPipeAotThreadHolderTLS::getThreadHolder ();
+    if (!thread_holder)
+        thread_holder = EventPipeAotThreadHolderTLS::createThreadHolder ();
+
+    return ep_thread_holder_get_thread (thread_holder);
+}
+
+static
+inline
+ep_rt_thread_handle_t
+ep_rt_thread_get_handle (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // return GetThreadNULLOk ();
+    return NULL;
+}
+
+static
+inline
+ep_rt_thread_id_t
+ep_rt_thread_get_id (ep_rt_thread_handle_t thread_handle)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (thread_handle != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // return ep_rt_uint64_t_to_thread_id_t (thread_handle->GetOSThreadId64 ());
+    // PalDebugBreak();
+    return 0;
+}
+
+static
+inline
+uint64_t
+ep_rt_thread_id_t_to_uint64_t (ep_rt_thread_id_t thread_id)
+{
+    return static_cast<uint64_t>(thread_id);
+}
+
+static
+inline
+ep_rt_thread_id_t
+ep_rt_uint64_t_to_thread_id_t (uint64_t thread_id)
+{
+    return static_cast<ep_rt_thread_id_t>(thread_id);
+}
+
+static
+inline
+bool
+ep_rt_thread_has_started (ep_rt_thread_handle_t thread_handle)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // return thread_handle != NULL && thread_handle->HasStarted ();
+    return true;
+}
+
+static
+inline
+ep_rt_thread_activity_id_handle_t
+ep_rt_thread_get_activity_id_handle (void)
+{
+    STATIC_CONTRACT_NOTHROW;
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // return GetThread ();
+    // PalDebugBreak();
+    return NULL;
+}
+
+static
+inline
+const uint8_t *
+ep_rt_thread_get_activity_id_cref (ep_rt_thread_activity_id_handle_t activity_id_handle)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (activity_id_handle != NULL);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // return reinterpret_cast<const uint8_t *>(activity_id_handle->GetActivityId ());
+    // PalDebugBreak();
+    return NULL;
+}
+
+static
+inline
+void
+ep_rt_thread_get_activity_id (
+    ep_rt_thread_activity_id_handle_t activity_id_handle,
+    uint8_t *activity_id,
+    uint32_t activity_id_len)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (activity_id_handle != NULL);
+    EP_ASSERT (activity_id != NULL);
+    EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE);
+
+    memcpy (activity_id, ep_rt_thread_get_activity_id_cref (activity_id_handle), EP_ACTIVITY_ID_SIZE);
+}
+
+static
+inline
+void
+ep_rt_thread_set_activity_id (
+    ep_rt_thread_activity_id_handle_t activity_id_handle,
+    const uint8_t *activity_id,
+    uint32_t activity_id_len)
+{
+    STATIC_CONTRACT_NOTHROW;
+    EP_ASSERT (activity_id_handle != NULL);
+    EP_ASSERT (activity_id != NULL);
+    EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE);
+
+    // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
+    // TODO: Implement thread creation/management if needed
+    // activity_id_handle->SetActivityId (reinterpret_cast<LPCGUID>(activity_id));
+    // PalDebugBreak();
+}
+
+#undef EP_YIELD_WHILE
+#define EP_YIELD_WHILE(condition) {}//YIELD_WHILE(condition)
+
+/*
+ * ThreadSequenceNumberMap.
+ */
+
+EP_RT_DEFINE_HASH_MAP_REMOVE(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, EventPipeThreadSessionState *, uint32_t)
+EP_RT_DEFINE_HASH_MAP_ITERATOR(thread_sequence_number_map, ep_rt_thread_sequence_number_hash_map_t, ep_rt_thread_sequence_number_hash_map_iterator_t, EventPipeThreadSessionState *, uint32_t)
+
+/*
+ * Volatile.
+ */
+
+static
+inline
+uint32_t
+ep_rt_volatile_load_uint32_t (const volatile uint32_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint32_t
+    ep_rt_aot_volatile_load_uint32_t (const volatile uint32_t *ptr);
+    return ep_rt_aot_volatile_load_uint32_t(ptr);
+}
+
+static
+inline
+uint32_t
+ep_rt_volatile_load_uint32_t_without_barrier (const volatile uint32_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint32_t
+    ep_rt_aot_volatile_load_uint32_t_without_barrier (const volatile uint32_t *ptr);
+
+    return ep_rt_aot_volatile_load_uint32_t_without_barrier(ptr);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_uint32_t (
+    volatile uint32_t *ptr,
+    uint32_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_uint32_t (
+    volatile uint32_t *ptr,
+    uint32_t value);
+
+    ep_rt_aot_volatile_store_uint32_t(ptr, value);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_uint32_t_without_barrier (
+    volatile uint32_t *ptr,
+    uint32_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_uint32_t_without_barrier (
+    volatile uint32_t *ptr,
+    uint32_t value);
+
+    ep_rt_aot_volatile_store_uint32_t_without_barrier(ptr, value);
+}
+
+static
+inline
+uint64_t
+ep_rt_volatile_load_uint64_t (const volatile uint64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint64_t
+    ep_rt_aot_volatile_load_uint64_t (const volatile uint64_t *ptr);
+
+    return ep_rt_aot_volatile_load_uint64_t(ptr);
+}
+
+static
+inline
+uint64_t
+ep_rt_volatile_load_uint64_t_without_barrier (const volatile uint64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern uint64_t
+    ep_rt_aot_volatile_load_uint64_t_without_barrier (const volatile uint64_t *ptr);
+
+    return ep_rt_aot_volatile_load_uint64_t_without_barrier(ptr);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_uint64_t (
+    volatile uint64_t *ptr,
+    uint64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_uint64_t (
+    volatile uint64_t *ptr,
+    uint64_t value);
+
+    ep_rt_aot_volatile_store_uint64_t(ptr, value);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_uint64_t_without_barrier (
+    volatile uint64_t *ptr,
+    uint64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_uint64_t_without_barrier (
+    volatile uint64_t *ptr,
+    uint64_t value);
+    ep_rt_aot_volatile_store_uint64_t_without_barrier(ptr, value);
+}
+
+static
+inline
+int64_t
+ep_rt_volatile_load_int64_t (const volatile int64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int64_t
+    ep_rt_aot_volatile_load_int64_t (const volatile int64_t *ptr);
+    return ep_rt_aot_volatile_load_int64_t(ptr);
+}
+
+static
+inline
+int64_t
+ep_rt_volatile_load_int64_t_without_barrier (const volatile int64_t *ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern int64_t
+    ep_rt_aot_volatile_load_int64_t_without_barrier (const volatile int64_t *ptr);
+    return ep_rt_aot_volatile_load_int64_t_without_barrier(ptr);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_int64_t (
+    volatile int64_t *ptr,
+    int64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_int64_t (
+    volatile int64_t *ptr,
+    int64_t value);
+    ep_rt_aot_volatile_store_int64_t(ptr, value);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_int64_t_without_barrier (
+    volatile int64_t *ptr,
+    int64_t value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_int64_t_without_barrier (
+    volatile int64_t *ptr,
+    int64_t value);
+    ep_rt_aot_volatile_store_int64_t_without_barrier(ptr, value);
+}
+
+static
+inline
+void *
+ep_rt_volatile_load_ptr (volatile void **ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void *
+    ep_rt_aot_volatile_load_ptr (volatile void **ptr);
+    return ep_rt_aot_volatile_load_ptr(ptr);
+}
+
+static
+inline
+void *
+ep_rt_volatile_load_ptr_without_barrier (volatile void **ptr)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void *
+    ep_rt_aot_volatile_load_ptr_without_barrier (volatile void **ptr);
+    return ep_rt_aot_volatile_load_ptr_without_barrier(ptr);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_ptr (
+    volatile void **ptr,
+    void *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_ptr (
+    volatile void **ptr,
+    void *value);
+    ep_rt_aot_volatile_store_ptr(ptr, value);
+}
+
+static
+inline
+void
+ep_rt_volatile_store_ptr_without_barrier (
+    volatile void **ptr,
+    void *value)
+{
+    STATIC_CONTRACT_NOTHROW;
+    extern void
+    ep_rt_aot_volatile_store_ptr_without_barrier (
+    volatile void **ptr,
+    void *value);
+    ep_rt_aot_volatile_store_ptr_without_barrier(ptr, value);
+}
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __EVENTPIPE_RT_AOT_H__ */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-config-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-config-aot.h
new file mode 100644 (file)
index 0000000..d42cad6
--- /dev/null
@@ -0,0 +1,4 @@
+#ifndef __EVENTPIPE_RT_CONFIG_AOT_H__
+#define __EVENTPIPE_RT_CONFIG_AOT_H__
+
+#endif /* __EVENTPIPE_RT_CONFIG_AOT_H__ */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h
new file mode 100644 (file)
index 0000000..9aa547e
--- /dev/null
@@ -0,0 +1,347 @@
+// Implementation of ep-rt-types.h targeting AOT runtime.
+#ifndef __EVENTPIPE_RT_TYPES_AOT_H__
+#define __EVENTPIPE_RT_TYPES_AOT_H__
+
+#include <eventpipe/ep-rt-config.h>
+
+#include <inttypes.h>
+
+#ifdef ENABLE_PERFTRACING
+
+#include "EmptyContainers.h"
+
+#ifdef TARGET_UNIX
+#define __stdcall
+#endif
+
+#ifdef DEBUG
+#define EP_CHECKED_BUILD
+#endif
+
+#undef EP_ASSERT
+#ifdef EP_CHECKED_BUILD
+#define EP_ASSERT(expr) _ASSERTE(expr)
+#else
+#define EP_ASSERT(expr)
+#endif
+
+#undef EP_UNREACHABLE
+#define EP_UNREACHABLE(msg) do { UNREACHABLE_MSG(msg); } while (0)
+
+#undef EP_LIKELY
+#define EP_LIKELY(expr) expr
+
+#undef EP_UNLIKELY
+#define EP_UNLIKELY(expr) expr
+
+template<typename T>
+struct _rt_aot_list_internal_t {
+    typedef struct SListElem_EP<T> element_type_t;
+    typedef class SList_EP<element_type_t> list_type_t;
+    list_type_t *list;
+};
+
+template<typename T>
+struct _rt_aot_queue_internal_t {
+    typedef struct SListElem_EP<T> element_type_t;
+    typedef class SList_EP<element_type_t> queue_type_t;
+    queue_type_t *queue;
+};
+
+template<typename T>
+struct _rt_aot_array_internal_t {
+    typedef T element_type_t;
+    typedef class CQuickArrayList_EP<T> array_type_t;
+    array_type_t *array;
+};
+
+template<typename T>
+struct _rt_aot_array_iterator_internal_t {
+    typedef typename _rt_aot_array_internal_t<T>::array_type_t array_iterator_type;
+    array_iterator_type *array;
+    size_t index;
+};
+
+typedef struct _rt_aot_table_callbacks_t {
+    void (*key_free_func)(void *);
+    void (*value_free_func)(void *);
+} rt_aot_table_callbacks_t;
+
+template<typename T1, typename T2>
+struct _rt_aot_table_default_internal_t {
+    typedef class SHash_EP<NoRemoveSHashTraits_EP< MapSHashTraits_EP <T1, T2> > > table_type_t;
+    rt_aot_table_callbacks_t callbacks;
+    table_type_t *table;
+};
+
+template<typename T1, typename T2>
+struct _rt_aot_table_remove_internal_t {
+    typedef class SHash_EP< MapSHashTraits_EP <T1, T2> > table_type_t;
+    rt_aot_table_callbacks_t callbacks;
+    table_type_t *table;
+};
+
+class EventPipeAotStackHashTraits : public NoRemoveSHashTraits_EP< MapSHashTraits_EP<StackHashKey *, StackHashEntry *> >
+{
+public:
+    typedef typename MapSHashTraits_EP<StackHashKey *, StackHashEntry *>::element_t element_t;
+    typedef typename MapSHashTraits_EP<StackHashKey *, StackHashEntry *>::count_t count_t;
+
+    typedef StackHashKey * key_t;
+
+    static key_t GetKey (element_t e)
+    {
+        extern StackHashKey * ep_stack_hash_entry_get_key (StackHashEntry *);
+        return ep_stack_hash_entry_get_key (e.Value ());
+    }
+
+    static bool Equals (key_t k1, key_t k2)
+    {
+        extern bool ep_stack_hash_key_equal (const void *, const void *);
+        return ep_stack_hash_key_equal (k1, k2);
+    }
+
+    static count_t Hash (key_t k)
+    {
+        extern uint32_t ep_stack_hash_key_hash (const void *);
+        return (count_t)ep_stack_hash_key_hash (k);
+    }
+
+    static element_t Null ()
+    {
+        return element_t (NULL, NULL);
+    }
+
+    static bool IsNull (const element_t &e)
+    {
+        return (e.Key () == NULL|| e.Value () == NULL);
+    }
+};
+
+template<typename T1>
+struct _rt_aot_table_custom_internal_t {
+    typedef class SHash_EP<T1> table_type_t;
+    rt_aot_table_callbacks_t callbacks;
+    table_type_t *table;
+};
+
+class CLREventStatic;
+struct _rt_aot_event_internal_t {
+    CLREventStatic *event;
+};
+
+class CrstStatic;
+struct _rt_aot_lock_internal_t {
+    CrstStatic *lock;
+};
+
+class SpinLock;
+struct _rt_aot_spin_lock_internal_t {
+    SpinLock *lock;
+};
+
+/*
+ * EventPipeBuffer.
+ */
+
+#undef ep_rt_buffer_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeBuffer *> ep_rt_buffer_array_t;
+
+#undef ep_rt_buffer_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeBuffer *> ep_rt_buffer_array_iterator_t;
+
+/*
+ * EventPipeBufferList.
+ */
+
+#undef ep_rt_buffer_list_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeBufferList *> ep_rt_buffer_list_array_t;
+
+#undef ep_rt_buffer_list_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeBufferList *> ep_rt_buffer_list_array_iterator_t;
+
+/*
+ * EventPipeEvent.
+ */
+
+#undef ep_rt_event_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeEvent *> ep_rt_event_list_t;
+
+#undef ep_rt_event_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeEvent *>::list_type_t::Iterator ep_rt_event_list_iterator_t;
+
+/*
+ * EventPipeFile.
+ */
+
+#undef ep_rt_metadata_labels_hash_map_t
+typedef struct _rt_aot_table_remove_internal_t<EventPipeEvent *, uint32_t> ep_rt_metadata_labels_hash_map_t;
+
+#undef ep_rt_metadata_labels_hash_map_iterator_t
+typedef class _rt_aot_table_remove_internal_t<EventPipeEvent *, uint32_t>::table_type_t::Iterator ep_rt_metadata_labels_hash_map_iterator_t;
+
+#undef ep_rt_stack_hash_map_t
+typedef struct _rt_aot_table_custom_internal_t<EventPipeAotStackHashTraits> ep_rt_stack_hash_map_t;
+
+#undef ep_rt_stack_hash_map_iterator_t
+typedef class _rt_aot_table_custom_internal_t<EventPipeAotStackHashTraits>::table_type_t::Iterator ep_rt_stack_hash_map_iterator_t;
+
+/*
+ * EventPipeProvider.
+ */
+
+#undef ep_rt_provider_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeProvider *> ep_rt_provider_list_t;
+
+#undef ep_rt_provider_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeProvider *>::list_type_t::Iterator ep_rt_provider_list_iterator_t;
+
+#undef ep_rt_provider_callback_data_queue_t
+typedef struct _rt_aot_queue_internal_t<EventPipeProviderCallbackData *> ep_rt_provider_callback_data_queue_t;
+
+/*
+ * EventPipeProviderConfiguration.
+ */
+
+#undef ep_rt_provider_config_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeProviderConfiguration> ep_rt_provider_config_array_t;
+
+#undef ep_rt_provider_config_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeProviderConfiguration> ep_rt_provider_config_array_iterator_t;
+
+/*
+ * EventPipeSessionProvider.
+ */
+
+#undef ep_rt_session_provider_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeSessionProvider *> ep_rt_session_provider_list_t;
+
+#undef ep_rt_session_provider_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeSessionProvider *>::list_type_t::Iterator ep_rt_session_provider_list_iterator_t;
+
+/*
+ * EventPipeSequencePoint.
+ */
+
+#undef ep_rt_sequence_point_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeSequencePoint *> ep_rt_sequence_point_list_t;
+
+#undef ep_rt_sequence_point_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeSequencePoint *>::list_type_t::Iterator ep_rt_sequence_point_list_iterator_t;
+
+/*
+ * EventPipeThread.
+ */
+
+#undef ep_rt_thread_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeThread *> ep_rt_thread_list_t;
+
+#undef ep_rt_thread_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeThread *>::list_type_t::Iterator ep_rt_thread_list_iterator_t;
+
+#undef ep_rt_thread_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeThread *> ep_rt_thread_array_t;
+
+#undef ep_rt_thread_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeThread *> ep_rt_thread_array_iterator_t;
+
+/*
+ * EventPipeThreadSessionState.
+ */
+
+#undef ep_rt_thread_session_state_list_t
+typedef struct _rt_aot_list_internal_t<EventPipeThreadSessionState *> ep_rt_thread_session_state_list_t;
+
+#undef ep_rt_thread_session_state_list_iterator_t
+typedef class _rt_aot_list_internal_t<EventPipeThreadSessionState *>::list_type_t::Iterator ep_rt_thread_session_state_list_iterator_t;
+
+#undef ep_rt_thread_session_state_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeThreadSessionState *> ep_rt_thread_session_state_array_t;
+
+#undef ep_rt_thread_session_state_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeThreadSessionState *> ep_rt_thread_session_state_array_iterator_t;
+
+/*
+ * EventPipe.
+ */
+
+#undef ep_rt_session_id_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeSessionID> ep_rt_session_id_array_t;
+
+#undef ep_rt_session_id_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeSessionID> ep_rt_session_id_array_iterator_t;
+
+#undef ep_rt_method_desc_t
+typedef class MethodDesc ep_rt_method_desc_t;
+
+#undef ep_rt_execution_checkpoint_array_t
+typedef struct _rt_aot_array_internal_t<EventPipeExecutionCheckpoint *> ep_rt_execution_checkpoint_array_t;
+
+#undef ep_rt_execution_checkpoint_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<EventPipeExecutionCheckpoint *> ep_rt_execution_checkpoint_array_iterator_t;
+
+/*
+ * PAL.
+ */
+
+#undef ep_rt_env_array_utf16_t
+typedef struct _rt_aot_array_internal_t<ep_char16_t *> ep_rt_env_array_utf16_t;
+
+#undef ep_rt_env_array_utf16_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t<ep_char16_t *> ep_rt_env_array_utf16_iterator_t;
+
+#undef ep_rt_file_handle_t
+typedef class CFileStream * ep_rt_file_handle_t;
+
+#undef ep_rt_wait_event_handle_t
+typedef struct _rt_aot_event_internal_t ep_rt_wait_event_handle_t;
+
+#undef ep_rt_lock_handle_t
+typedef struct _rt_aot_lock_internal_t ep_rt_lock_handle_t;
+
+#undef ep_rt_spin_lock_handle_t
+typedef _rt_aot_spin_lock_internal_t ep_rt_spin_lock_handle_t;
+
+/*
+ * Thread.
+ */
+
+#undef ep_rt_thread_handle_t
+typedef class Thread * ep_rt_thread_handle_t;
+
+#undef ep_rt_thread_activity_id_handle_t
+typedef class Thread * ep_rt_thread_activity_id_handle_t;
+
+#undef ep_rt_thread_id_t
+// #ifndef TARGET_UNIX
+// typedef DWORD ep_rt_thread_id_t;
+// #else
+typedef size_t ep_rt_thread_id_t;
+//#endif
+
+#undef ep_rt_thread_start_func
+typedef size_t (__stdcall *ep_rt_thread_start_func)(void *lpThreadParameter);
+
+#undef ep_rt_thread_start_func_return_t
+typedef size_t ep_rt_thread_start_func_return_t;
+
+#undef ep_rt_thread_params_t
+typedef struct _rt_aot_thread_params_t {
+    ep_rt_thread_handle_t thread;
+    EventPipeThreadType thread_type;
+    ep_rt_thread_start_func thread_func;
+    void *thread_params;
+} ep_rt_thread_params_t;
+
+/*
+ * ThreadSequenceNumberMap.
+ */
+
+#undef ep_rt_thread_sequence_number_hash_map_t
+typedef struct _rt_aot_table_remove_internal_t<EventPipeThreadSessionState *, uint32_t> ep_rt_thread_sequence_number_hash_map_t;
+
+#undef ep_rt_thread_sequence_number_hash_map_iterator_t
+typedef class _rt_aot_table_remove_internal_t<EventPipeThreadSessionState *, uint32_t>::table_type_t::Iterator ep_rt_thread_sequence_number_hash_map_iterator_t;
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __EVENTPIPE_RT_TYPES_AOT_H__ */
diff --git a/src/coreclr/nativeaot/Runtime/eventpipeadapter.h b/src/coreclr/nativeaot/Runtime/eventpipeadapter.h
new file mode 100644 (file)
index 0000000..4156cbf
--- /dev/null
@@ -0,0 +1,154 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __EVENTPIPE_ADAPTER_H__
+#define __EVENTPIPE_ADAPTER_H__
+
+#if defined(FEATURE_PERFTRACING)
+
+#include <eventpipe/ep.h>
+#include <eventpipe/ep-provider.h>
+#include <eventpipe/ep-config.h>
+#include <eventpipe/ep-event.h>
+#include <eventpipe/ep-event-instance.h>
+#include <eventpipe/ep-session.h>
+#include <eventpipe/ep-session-provider.h>
+#include <eventpipe/ep-metadata-generator.h>
+#include <eventpipe/ep-event-payload.h>
+#include <eventpipe/ep-buffer-manager.h>
+
+#include "gcenv.h"
+#include "regdisplay.h"
+#include "StackFrameIterator.h"
+#include "thread.h"
+#include "holder.h"
+#include "SpinLock.h"
+
+class EventPipeAdapter final
+{
+public:
+    static inline void Initialize()
+    {
+        CONTRACTL
+        {
+            NOTHROW;
+        }
+        CONTRACTL_END;
+
+        ep_init();
+    }
+
+    static inline EventPipeProvider * CreateProvider(LPCWSTR providerName, EventPipeCallback callback, void* pCallbackContext)
+    {
+        ep_char8_t *providerNameUTF8 = ep_rt_utf16_to_utf8_string(reinterpret_cast<const ep_char16_t *>(providerName), -1);
+        EventPipeProvider * provider = ep_create_provider (providerNameUTF8, callback, pCallbackContext);
+        ep_rt_utf8_string_free (providerNameUTF8);
+        return provider;
+    }
+
+    static inline void DeleteProvider (EventPipeProvider * provider)
+    {
+        ep_delete_provider (provider);
+    }
+
+
+    static inline void FinishInitialize()
+    {
+        CONTRACTL
+        {
+            NOTHROW;
+        }
+        CONTRACTL_END;
+
+        ep_finish_init();
+    }
+
+    static inline void Shutdown()
+    {
+        ep_shutdown();
+    }
+
+    static inline bool Enabled()
+    {
+        STATIC_CONTRACT_NOTHROW;
+        return ep_enabled();
+    }
+
+    static inline void Disable(EventPipeSessionID id)
+    {
+        CONTRACTL
+        {
+            NOTHROW;
+            GC_TRIGGERS;
+            MODE_ANY;
+        }
+        CONTRACTL_END;
+
+        ep_disable(id);
+    }
+
+    static inline EventPipeProvider * GetProvider (LPCWSTR providerName)
+    {
+        CONTRACTL
+        {
+            NOTHROW;
+            GC_NOTRIGGER;
+            MODE_ANY;
+        }
+        CONTRACTL_END;
+
+        if (!providerName)
+            return NULL;
+
+        ep_char8_t *providerNameUTF8 = ep_rt_utf16_to_utf8_string(reinterpret_cast<const ep_char16_t *>(providerName), -1);
+        EventPipeProvider * provider = ep_get_provider (providerNameUTF8);
+        ep_rt_utf8_string_free(providerNameUTF8);
+        return provider;
+    }
+
+    static inline EventPipeEvent * AddEvent(
+        EventPipeProvider *provider,
+        uint32_t eventID,
+        int64_t keywords,
+        uint32_t eventVersion,
+        EventPipeEventLevel level,
+        bool needStack,
+        uint8_t *metadata = NULL,
+        uint32_t metadataLen = 0)
+    {
+        return ep_provider_add_event(provider, eventID, keywords, eventVersion, level, needStack, metadata, metadataLen);
+    }
+
+    static inline void WriteEvent(
+        EventPipeEvent *ep_event,
+        uint8_t *data,
+        uint32_t dataLen,
+        const GUID * activityId,
+        const GUID * relatedActivityId)
+    {
+        ep_write_event(
+            ep_event,
+            data,
+            dataLen,
+            reinterpret_cast<const uint8_t*>(activityId),
+            reinterpret_cast<const uint8_t*>(relatedActivityId));
+    }
+
+    static inline void WriteEvent(
+        EventPipeEvent *ep_event,
+        EventData *data,
+        uint32_t dataLen,
+        const GUID * activityId,
+        const GUID * relatedActivityId)
+    {
+        ep_write_event_2(
+            ep_event,
+            data,
+            dataLen,
+            reinterpret_cast<const uint8_t*>(activityId),
+            reinterpret_cast<const uint8_t*>(relatedActivityId));
+    }
+};
+
+#endif // FEATURE_PERFTRACING
+#endif // __EVENTPIPE_ADAPTER_H__
diff --git a/src/coreclr/nativeaot/Runtime/eventpipeadaptertypes.h b/src/coreclr/nativeaot/Runtime/eventpipeadaptertypes.h
new file mode 100644 (file)
index 0000000..f473bde
--- /dev/null
@@ -0,0 +1,15 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#ifndef __EVENTPIPE_ADAPTER_TYPES_H__
+#define __EVENTPIPE_ADAPTER_TYPES_H__
+
+#if defined(FEATURE_PERFTRACING)
+
+typedef struct _EventFilterDescriptor EventFilterDescriptor;
+typedef struct _EventPipeBufferList EventPipeBufferList;
+typedef struct _EventPipeProvider EventPipeProvider;
+typedef struct _EventPipeSession EventPipeSession;
+
+#endif // FEATURE_PERFTRACING
+#endif // __EVENTPIPE_ADAPTER_TYPES_H__
diff --git a/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp b/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp
new file mode 100644 (file)
index 0000000..3615daa
--- /dev/null
@@ -0,0 +1,135 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+#include "common.h"
+#include "eventpipeadapter.h"
+
+#include "gcenv.h"
+#include "regdisplay.h"
+#include "StackFrameIterator.h"
+#include "thread.h"
+#include "SpinLock.h"
+
+#ifdef FEATURE_PERFTRACING
+
+struct EventPipeEventInstanceData
+{
+    void *ProviderID;
+    unsigned int EventID;
+    unsigned int ThreadID;
+    LARGE_INTEGER TimeStamp;
+    GUID ActivityId;
+    GUID RelatedActivityId;
+    const uint8_t *Payload;
+    unsigned int PayloadLength;
+};
+
+struct EventPipeSessionInfo
+{
+    FILETIME StartTimeAsUTCFileTime;
+    LARGE_INTEGER StartTimeStamp;
+    LARGE_INTEGER TimeStampFrequency;
+};
+
+EXTERN_C NATIVEAOT_API uint64_t __cdecl RhEventPipeInternal_Enable(
+    LPCWSTR outputFile,
+    EventPipeSerializationFormat format,
+    uint32_t circularBufferSizeInMB,
+    /* COR_PRF_EVENTPIPE_PROVIDER_CONFIG */ const void * pProviders,
+    uint32_t numProviders)
+{
+    PalDebugBreak();
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_Disable(uint64_t sessionID)
+{
+    EventPipeAdapter::Disable(sessionID);
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_CreateProvider(
+    LPCWSTR providerName,
+    EventPipeCallback pCallbackFunc,
+    void* pCallbackContext)
+{
+    EventPipeProvider* pProvider = EventPipeAdapter::CreateProvider(providerName, pCallbackFunc, pCallbackContext);
+    return reinterpret_cast<intptr_t>(pProvider);
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_DefineEvent(
+    intptr_t provHandle,
+    uint32_t eventID,
+    int64_t keywords,
+    uint32_t eventVersion,
+    uint32_t level,
+    void *pMetadata,
+    uint32_t metadataLength)
+{
+    EventPipeEvent *pEvent = NULL;
+
+    _ASSERTE(provHandle != 0);
+    EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
+    pEvent = EventPipeAdapter::AddEvent(pProvider, eventID, keywords, eventVersion, (EventPipeEventLevel)level, /* needStack = */ true, (uint8_t *)pMetadata, metadataLength);
+    _ASSERTE(pEvent != NULL);
+
+    return reinterpret_cast<intptr_t>(pEvent);
+}
+
+EXTERN_C NATIVEAOT_API intptr_t __cdecl RhEventPipeInternal_GetProvider(LPCWSTR providerName)
+{
+    EventPipeProvider* pProvider = EventPipeAdapter::GetProvider(providerName);
+    return reinterpret_cast<intptr_t>(pProvider);
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_DeleteProvider(intptr_t provHandle)
+{
+    if (provHandle != 0)
+    {
+        EventPipeProvider *pProvider = reinterpret_cast<EventPipeProvider *>(provHandle);
+        EventPipeAdapter::DeleteProvider(pProvider);
+    }
+}
+
+EXTERN_C NATIVEAOT_API int __cdecl RhEventPipeInternal_EventActivityIdControl(uint32_t controlCode, GUID *pActivityId)
+{
+    PalDebugBreak();
+    return 0;
+}
+
+EXTERN_C NATIVEAOT_API void __cdecl RhEventPipeInternal_WriteEventData(
+    intptr_t eventHandle,
+    EventData *pEventData,
+    uint32_t eventDataCount,
+    const GUID * pActivityId,
+    const GUID * pRelatedActivityId)
+{
+    _ASSERTE(eventHandle != 0);
+    EventPipeEvent *pEvent = reinterpret_cast<EventPipeEvent *>(eventHandle);
+    EventPipeAdapter::WriteEvent(pEvent, pEventData, eventDataCount, pActivityId, pRelatedActivityId);
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_GetSessionInfo(uint64_t sessionID, EventPipeSessionInfo *pSessionInfo)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_GetNextEvent(uint64_t sessionID, EventPipeEventInstanceData *pInstance)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_SignalSession(uint64_t sessionID)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+EXTERN_C NATIVEAOT_API UInt32_BOOL __cdecl RhEventPipeInternal_WaitForSessionSignal(uint64_t sessionID, int32_t timeoutMs)
+{
+    PalDebugBreak();
+    return FALSE;
+}
+
+#endif // FEATURE_PERFTRACING
index 9acfb0b..d1e2403 100644 (file)
 #include "RestrictedCallouts.h"
 #include "yieldprocessornormalized.h"
 
+#ifdef FEATURE_PERFTRACING
+#include "EventPipeInterface.h"
+#endif
+
 #ifndef DACCESS_COMPILE
 
 #ifdef PROFILE_STARTUP
@@ -97,6 +101,14 @@ static bool InitDLL(HANDLE hPalInstance)
         return false;
 #endif
 
+#ifdef FEATURE_PERFTRACING
+    // Initialize EventPipe
+    EventPipeAdapter_Initialize();
+    // Initialize DS
+    DiagnosticServerAdapter_Initialize();
+    DiagnosticServerAdapter_PauseForDiagnosticsMonitor();
+#endif
+
     //
     // Initialize support for registering GC and HandleTable callouts.
     //
@@ -141,6 +153,13 @@ static bool InitDLL(HANDLE hPalInstance)
 
     STARTUP_TIMELINE_EVENT(GC_INIT_COMPLETE);
 
+#ifdef FEATURE_PERFTRACING
+    // Finish setting up rest of EventPipe - specifically enable SampleProfiler if it was requested at startup.
+    // SampleProfiler needs to cooperate with the GC which hasn't fully finished setting up in the first part of the
+    // EventPipe initialization, so this is done after the GC has been fully initialized.
+    EventPipeAdapter_FinishInitialize();
+#endif
+
 #ifndef USE_PORTABLE_HELPERS
     if (!DetectCPUFeatures())
         return false;
@@ -459,6 +478,11 @@ static void __cdecl OnProcessExit()
     // or run managed code at shutdown, so we will not try detaching it.
     Thread* currentThread = ThreadStore::RawGetCurrentThread();
     g_threadPerformingShutdown = currentThread;
+
+#ifdef FEATURE_PERFTRACING
+    EventPipeAdapter_Shutdown();
+    DiagnosticServerAdapter_Shutdown();
+#endif
 }
 #endif
 
index 698d88a..d42a78e 100644 (file)
@@ -331,10 +331,8 @@ typedef DacScanCallbackData EnumGcRefScanContext;
 typedef void EnumGcRefCallbackFunc(PTR_PTR_Object, EnumGcRefScanContext* callbackData, uint32_t flags);
 
 #else // DACCESS_COMPILE
-#ifndef __GCENV_BASE_INCLUDED__
 struct ScanContext;
 typedef void promote_func(PTR_PTR_Object, ScanContext*, unsigned);
-#endif // !__GCENV_BASE_INCLUDED__
 typedef promote_func EnumGcRefCallbackFunc;
 typedef ScanContext  EnumGcRefScanContext;
 
index 4750908..9eb54fb 100644 (file)
@@ -632,6 +632,11 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCal
 #endif // HOST_WASM
 }
 
+REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartEventPipeHelperThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext)
+{
+    return PalStartBackgroundWork(callback, pCallbackContext, UInt32_FALSE);
+}
+
 // Returns a 64-bit tick count with a millisecond resolution. It tries its best
 // to return monotonically increasing counts and avoid being affected by changes
 // to the system clock (either due to drift or due to explicit changes to system
index e6e304e..2d53bbf 100644 (file)
@@ -624,6 +624,11 @@ REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartFinalizerThread(_In_ BackgroundCal
     return PalStartBackgroundWork(callback, pCallbackContext, TRUE);
 }
 
+REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalStartEventPipeHelperThread(_In_ BackgroundCallback callback, _In_opt_ void* pCallbackContext)
+{
+    return PalStartBackgroundWork(callback, pCallbackContext, FALSE);
+}
+
 REDHAWK_PALEXPORT bool REDHAWK_PALAPI PalEventEnabled(REGHANDLE regHandle, _In_ const EVENT_DESCRIPTOR* eventDescriptor)
 {
     return !!EventEnabled(regHandle, eventDescriptor);
index 4739cac..e9a18dc 100644 (file)
     <Compile Include="System\Diagnostics\StackFrame.NativeAot.cs" />
     <Compile Include="System\Diagnostics\StackFrameExtensions.cs" />
     <Compile Include="System\Diagnostics\StackTrace.NativeAot.cs" />
+    <Compile Include="System\Diagnostics\Eventing\EventPipe.NativeAot.cs" />
     <Compile Include="System\Enum.NativeAot.cs" />
     <Compile Include="System\Environment.NativeAot.cs" />
     <Compile Include="System\GC.NativeAot.cs" />
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Diagnostics/Eventing/EventPipe.NativeAot.cs
new file mode 100644 (file)
index 0000000..1a29085
--- /dev/null
@@ -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.
+using System.Runtime;
+using System.Runtime.InteropServices;
+
+#if FEATURE_PERFTRACING
+
+namespace System.Diagnostics.Tracing
+{
+    //
+    // NOTE:
+    //
+    // The implementation below takes some manual marshaling actions to ensure arguments are in
+    // primitive form before they are passed through to the underlying RuntimeImports.Rh*
+    // function.
+    //
+    // These extra steps are necessary only if the RuntimeImports mechanism represents "raw"
+    // calls into the native runtime (as has been the case at least in the distant past).
+    //
+    // If the RuntimeImports mechanism automatically applies rich p/invoke marshaling to all of
+    // these calls, then all of the manual steps below are unnecessary and can be removed (by
+    // making the RuntimeImports.Rh* function signatures generally match the corresponding
+    // EventPipeInternal function signatures; in other words, by making the RuntimeImports.Rh*
+    // functions look like the QCalls in EventPipe.CoreCLR.cs).
+    //
+    internal static partial class EventPipeInternal
+    {
+        //
+        // These PInvokes are used by the configuration APIs to interact with EventPipe.
+        //
+        private static unsafe ulong Enable(
+            char* outputFile,
+            EventPipeSerializationFormat format,
+            uint circularBufferSizeInMB,
+            EventPipeProviderConfigurationNative* providers,
+            uint numProviders)
+        {
+            return RuntimeImports.RhEventPipeInternal_Enable(
+                outputFile,
+                (int)format,
+                circularBufferSizeInMB,
+                providers,
+                numProviders);
+        }
+
+        internal static void Disable(ulong sessionID)
+        {
+            RuntimeImports.RhEventPipeInternal_Disable(sessionID);
+        }
+
+        //
+        // These PInvokes are used by EventSource to interact with the EventPipe.
+        //
+
+//        private static extern unsafe IntPtr CreateProvider(string providerName, IntPtr callbackFunc, IntPtr callbackContext);
+
+        internal static unsafe IntPtr CreateProvider(string providerName,
+                    delegate* unmanaged<byte*, int, byte, long, long, Interop.Advapi32.EVENT_FILTER_DESCRIPTOR*, void*, void> callbackFunc,
+                    void* callbackContext)
+                    => CreateProvider(providerName, (IntPtr)callbackFunc, (IntPtr)callbackContext);
+        //internal static unsafe IntPtr CreateProvider(string providerName, IntPtr callbackFunc, IntPtr callbackContext);
+
+        internal static unsafe IntPtr CreateProvider(string providerName, IntPtr callbackFunc, IntPtr callbackContext)
+        {
+            fixed (char* pProviderName = providerName)
+            {
+                return RuntimeImports.RhEventPipeInternal_CreateProvider(
+                    pProviderName,
+                    callbackFunc,
+                    callbackContext);
+            }
+        }
+
+        internal static unsafe IntPtr DefineEvent(
+            IntPtr provHandle,
+            uint eventID,
+            long keywords,
+            uint eventVersion,
+            uint level,
+            void *pMetadata,
+            uint metadataLength)
+        {
+            return RuntimeImports.RhEventPipeInternal_DefineEvent(
+                provHandle,
+                eventID,
+                keywords,
+                eventVersion,
+                level,
+                pMetadata,
+                metadataLength);
+        }
+
+        internal static unsafe IntPtr GetProvider(string providerName)
+        {
+            fixed (char* pProviderName = providerName)
+            {
+                return RuntimeImports.RhEventPipeInternal_GetProvider(pProviderName);
+            }
+        }
+
+        internal static void DeleteProvider(IntPtr provHandle)
+        {
+            RuntimeImports.RhEventPipeInternal_DeleteProvider(provHandle);
+        }
+
+        internal static unsafe int EventActivityIdControl(uint controlCode, ref Guid activityId)
+        {
+            //
+            // Ensure that the address passed to native code is never on the managed heap, while still
+            // managing the supplied byref in an in/out manner.
+            //
+            Guid localActivityId = activityId;
+            try { return RuntimeImports.RhEventPipeInternal_EventActivityIdControl(controlCode, &localActivityId); }
+            finally { activityId = localActivityId; }
+        }
+
+        internal static unsafe void WriteEventData(
+            IntPtr eventHandle,
+            EventProvider.EventData* pEventData,
+            uint dataCount,
+            Guid* activityId,
+            Guid* relatedActivityId)
+        {
+            RuntimeImports.RhEventPipeInternal_WriteEventData(
+                eventHandle,
+                pEventData,
+                dataCount,
+                activityId,
+                relatedActivityId);
+        }
+
+        //
+        // These PInvokes are used as part of the EventPipeEventDispatcher.
+        //
+        internal static unsafe bool GetSessionInfo(ulong sessionID, EventPipeSessionInfo* pSessionInfo)
+        {
+            uint rawBool = RuntimeImports.RhEventPipeInternal_GetSessionInfo(sessionID, pSessionInfo);
+            return (rawBool != 0);
+        }
+
+        internal static unsafe bool GetNextEvent(ulong sessionID, EventPipeEventInstanceData* pInstance)
+        {
+            uint rawBool = RuntimeImports.RhEventPipeInternal_GetNextEvent(sessionID, pInstance);
+            return (rawBool != 0);
+        }
+
+        internal static bool SignalSession(ulong sessionID)
+        {
+            uint rawBool = RuntimeImports.RhEventPipeInternal_SignalSession(sessionID);
+            return (rawBool != 0);
+        }
+
+        internal static bool WaitForSessionSignal(ulong sessionID, int timeoutMs)
+        {
+            uint rawBool = RuntimeImports.RhEventPipeInternal_WaitForSessionSignal(sessionID, timeoutMs);
+            return (rawBool != 0);
+        }
+    }
+}
+
+#endif // FEATURE_PERFTRACING
+
index 91894b1..bb20336 100644 (file)
@@ -691,6 +691,78 @@ namespace System.Runtime
         [RuntimeImport(RuntimeLibrary, "RhpEtwExceptionThrown")]
         internal static extern unsafe void RhpEtwExceptionThrown(char* exceptionTypeName, char* exceptionMessage, IntPtr faultingIP, long hresult);
 
+#if FEATURE_PERFTRACING
+
+        //
+        // EventPipeInternal helpers.
+        //
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial ulong RhEventPipeInternal_Enable(
+            char* outputFile,
+            int format,
+            uint circularBufferSizeInMB,
+            void* providers,
+            uint numProviders);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static partial void RhEventPipeInternal_Disable(ulong sessionID);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial IntPtr RhEventPipeInternal_CreateProvider(char* providerName, IntPtr callbackFunc, IntPtr callbackContext);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial IntPtr RhEventPipeInternal_DefineEvent(
+            IntPtr provHandle,
+            uint eventID,
+            long keywords,
+            uint eventVersion,
+            uint level,
+            void *pMetadata,
+            uint metadataLength);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial IntPtr RhEventPipeInternal_GetProvider(char* providerName);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static partial void RhEventPipeInternal_DeleteProvider(IntPtr provHandle);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial int RhEventPipeInternal_EventActivityIdControl(uint controlCode, Guid* activityId);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial void RhEventPipeInternal_WriteEventData(
+            IntPtr eventHandle,
+            void* pEventData,
+            uint dataCount,
+            Guid* activityId,
+            Guid* relatedActivityId);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial uint RhEventPipeInternal_GetSessionInfo(ulong sessionID, void* pSessionInfo);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static unsafe partial uint RhEventPipeInternal_GetNextEvent(ulong sessionID, void* pInstance);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static partial uint RhEventPipeInternal_SignalSession(ulong sessionID);
+
+        [LibraryImport(RuntimeLibrary)]
+        [UnmanagedCallConv(CallConvs = new Type[] { typeof(CallConvCdecl) })]
+        internal static partial uint RhEventPipeInternal_WaitForSessionSignal(ulong sessionID, int timeoutMs);
+
+#endif // FEATURE_PERFTRACING
+
         //
         // Interlocked helpers
         //
index ee8d329..2625139 100644 (file)
@@ -81,7 +81,7 @@
     <Link>
       <SubSystem>Console</SubSystem>
       <GenerateDebugInformation>true</GenerateDebugInformation>
-      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Debug\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\System.IO.Compression.Native.Aot.lib</AdditionalDependencies>
+      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Debug\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\System.IO.Compression.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Debug\aotsdk\eventpipe-disabled.lib</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Checked|x64'">
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Checked\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\System.IO.Compression.Native.Aot.lib</AdditionalDependencies>
+      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Checked\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\System.IO.Compression.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Checked\aotsdk\eventpipe-disabled.lib</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
       <GenerateDebugInformation>true</GenerateDebugInformation>
       <EnableCOMDATFolding>true</EnableCOMDATFolding>
       <OptimizeReferences>true</OptimizeReferences>
-      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Release\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\System.IO.Compression.Native.Aot.lib</AdditionalDependencies>
+      <AdditionalDependencies>$(ArtifactsRoot)bin\repro\x64\Release\repro.obj;$(Win32SDKLibs);%(AdditionalDependencies);$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\Runtime.WorkstationGC.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\System.Globalization.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\System.IO.Compression.Native.Aot.lib;$(ArtifactsRoot)bin\coreclr\windows.x64.Release\aotsdk\eventpipe-disabled.lib</AdditionalDependencies>
     </Link>
   </ItemDefinitionGroup>
   <ItemGroup>
index cc24d8f..22abed2 100644 (file)
@@ -4,6 +4,7 @@
     <TargetFrameworks>$(NetCoreAppCurrent);$(NetFrameworkMinimum)</TargetFrameworks>
     <EnableDefaultItems>true</EnableDefaultItems>
     <EventSourceSupport Condition="'$(TestNativeAot)' == 'true'">true</EventSourceSupport>
+    <EnableNativeEventPipe Condition="'$(TestNativeAot)' == 'true'">true</EnableNativeEventPipe>
   </PropertyGroup>
 
   <ItemGroup>
index 8001203..411f12f 100644 (file)
@@ -1,7 +1,12 @@
 <Project DefaultTargets="Build">
   <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props))" />
 
-  <ItemGroup>
+
+  <ItemGroup Condition="'$([MSBuild]::IsOSPlatform(Windows))' == 'true'">
+    <TestConsoleAppSourceFiles Include="DiagnosticSourceEventSourceTests.cs"
+                               EnabledProperties="EventSourceSupport;EnableNativeEventPipe" />
+  </ItemGroup>
+  <ItemGroup Condition="'$([MSBuild]::IsOSPlatform(Windows))' == 'false'">
     <TestConsoleAppSourceFiles Include="DiagnosticSourceEventSourceTests.cs"
                                EnabledProperties="EventSourceSupport" />
   </ItemGroup>
index 758e26d..5c01e52 100644 (file)
@@ -35,6 +35,8 @@ namespace System.Diagnostics.Tracing
         private IncrementingPollingCounter? _allocRateCounter;
         private PollingCounter? _timerCounter;
         private PollingCounter? _fragmentationCounter;
+
+#if !NATIVEAOT // TODO shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
         private PollingCounter? _committedCounter;
         private IncrementingPollingCounter? _exceptionCounter;
         private PollingCounter? _gcTimeCounter;
@@ -44,6 +46,8 @@ namespace System.Diagnostics.Tracing
         private PollingCounter? _lohSizeCounter;
         private PollingCounter? _pohSizeCounter;
         private PollingCounter? _assemblyCounter;
+#endif // !NATIVEAOT
+
         private PollingCounter? _ilBytesJittedCounter;
         private PollingCounter? _methodsJittedCounter;
         private IncrementingPollingCounter? _jitTimeCounter;
@@ -103,6 +107,8 @@ namespace System.Diagnostics.Tracing
                     var gcInfo = GC.GetGCMemoryInfo();
                     return gcInfo.HeapSizeBytes != 0 ? gcInfo.FragmentedBytes * 100d / gcInfo.HeapSizeBytes : 0;
                  }) { DisplayName = "GC Fragmentation", DisplayUnits = "%" };
+
+#if !NATIVEAOT // TODO
                 _committedCounter ??= new PollingCounter("gc-committed", this, () => ((double)GC.GetGCMemoryInfo().TotalCommittedBytes / 1_000_000)) { DisplayName = "GC Committed Bytes", DisplayUnits = "MB" };
                 _exceptionCounter ??= new IncrementingPollingCounter("exception-count", this, () => Exception.GetExceptionCount()) { DisplayName = "Exception Count", DisplayRateTimeScale = new TimeSpan(0, 0, 1) };
                 _gcTimeCounter ??= new PollingCounter("time-in-gc", this, () => GC.GetLastGCPercentTimeInGC()) { DisplayName = "% Time in GC since last GC", DisplayUnits = "%" };
@@ -112,6 +118,8 @@ namespace System.Diagnostics.Tracing
                 _lohSizeCounter ??= new PollingCounter("loh-size", this, () => GC.GetGenerationSize(3)) { DisplayName = "LOH Size", DisplayUnits = "B" };
                 _pohSizeCounter ??= new PollingCounter("poh-size", this, () => GC.GetGenerationSize(4)) { DisplayName = "POH (Pinned Object Heap) Size", DisplayUnits = "B" };
                 _assemblyCounter ??= new PollingCounter("assembly-count", this, () => System.Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" };
+#endif // !NATIVEAOT
+
                 _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" };
                 _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" };
                 _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) };
index 29446e4..45f17fe 100644 (file)
@@ -185,10 +185,12 @@ namespace System.Threading
 
 #if FEATURE_PERFTRACING
 #if !((TARGET_BROWSER || TARGET_WASI) && !FEATURE_WASM_THREADS)
+#if !NATIVEAOT // TODO shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase
                 if (NativeRuntimeEventSource.Log.IsEnabled())
                     NativeRuntimeEventSource.Log.ThreadPoolIOPack(pNativeOverlapped);
 #endif
 #endif
+#endif
 
                 NativeOverlapped* pRet = pNativeOverlapped;
                 pNativeOverlapped = null;
index 4d5a6cc..ea44752 100644 (file)
@@ -1,9 +1,9 @@
 #ifndef __EVENTPIPE_RT_CONFIG_H__
 #define __EVENTPIPE_RT_CONFIG_H__
 
-#include "ep-shared-config.h"
+#include <ep-shared-config.h>
 
-#ifndef FEATURE_CORECLR
+#if !defined(FEATURE_CORECLR) && !defined(FEATURE_NATIVEAOT)
 
 #include <config.h>
 
@@ -16,7 +16,7 @@
 #define DS_RT_H <mono/eventpipe/ds-rt-mono.h>
 #define DS_RT_TYPES_H <mono/eventpipe/ds-rt-types-mono.h>
 
-#else /* !FEATURE_CORECLR */
+#elif defined(FEATURE_CORECLR) 
 
 #ifndef EP_NO_RT_DEPENDENCY
 #include "common.h"
 #define DS_RT_H "ds-rt-coreclr.h"
 #define DS_RT_TYPES_H "ds-rt-types-coreclr.h"
 
+#elif defined(FEATURE_NATIVEAOT)
+
+#ifndef EP_NO_RT_DEPENDENCY
+#include "common.h"
+#endif
+
+#if defined(FEATURE_PERFTRACING)
+#define ENABLE_PERFTRACING
+#endif
+
+#ifdef TARGET_WINDOWS
+#define HOST_WIN32
+#endif
+
+#if defined(FEATURE_PERFTRACING) && defined(FEATURE_PROFAPI_ATTACH_DETACH) && defined(DACCESS_COMPILE)
+#undef FEATURE_PROFAPI_ATTACH_DETACH
+#endif
+
+#define EP_RT_H <eventpipe/ep-rt-aot.h>
+#define EP_RT_TYPES_H <eventpipe/ep-rt-types-aot.h>
+#define EP_RT_CONFIG_H <eventpipe/ep-rt-config-aot.h>
+
+#define DS_RT_H <eventpipe/ds-rt-aot.h>
+#define DS_RT_TYPES_H <eventpipe/ds-rt-types-aot.h>
+
 #endif
 
 #ifndef EP_NO_RT_DEPENDENCY
index 49e6e27..17c0562 100644 (file)
@@ -167,7 +167,7 @@ namespace Tracing.Tests.Common
             return -1;
         }
 
-        private int Validate()
+        private int Validate(bool enableRundownProvider = true)
         {
             // FIXME: This is a bandaid fix for a deadlock in EventPipeEventSource caused by
             // the lazy caching in the Regex library.  The caching creates a ConcurrentDictionary
@@ -212,7 +212,7 @@ namespace Tracing.Tests.Common
                 Logger.logger.Log("Connecting to EventPipe...");
                 try
                 {
-                    _eventPipeSession = client.StartEventPipeSession(_testProviders.Concat(_sentinelProviders));
+                    _eventPipeSession = client.StartEventPipeSession(_testProviders.Concat(_sentinelProviders), enableRundownProvider);
                 }
                 catch (DiagnosticsClientException ex)
                 {
@@ -392,13 +392,14 @@ namespace Tracing.Tests.Common
             Action eventGeneratingAction,
             List<EventPipeProvider> providers,
             int circularBufferMB=1024,
-            Func<EventPipeEventSource, Func<int>> optionalTraceValidator = null)
+            Func<EventPipeEventSource, Func<int>> optionalTraceValidator = null,
+            bool enableRundownProvider = true)
         {
             Logger.logger.Log("==TEST STARTING==");
             var test = new IpcTraceTest(expectedEventCounts, eventGeneratingAction, providers, circularBufferMB, optionalTraceValidator);
             try
             {
-                var ret = test.Validate();
+                var ret = test.Validate(enableRundownProvider);
                 if (ret == 100)
                     Logger.logger.Log("==TEST FINISHED: PASSED!==");
                 else
diff --git a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs b/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.cs
new file mode 100644 (file)
index 0000000..b6577fc
--- /dev/null
@@ -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.
+
+using System;
+using System.Diagnostics.Tracing;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Collections.Generic;
+using Microsoft.Diagnostics.Tracing;
+using Tracing.Tests.Common;
+using Microsoft.Diagnostics.NETCore.Client;
+
+namespace Tracing.Tests.SimpleProviderValidation
+{
+    public sealed class MyEventSource : EventSource
+    {
+        private MyEventSource() {}
+        public static MyEventSource Log = new MyEventSource();
+        public void MyEvent() { WriteEvent(1, "MyEvent"); }
+    }
+
+    public class ProviderValidation
+    {
+        public static int Main()
+        {
+            // This test validates that the rundown events are present
+            // and that providers turned on that generate events are being written to
+            // the stream.
+
+            var providers = new List<EventPipeProvider>()
+            {
+                new EventPipeProvider("MyEventSource", EventLevel.Verbose),
+                new EventPipeProvider("Microsoft-DotNETCore-SampleProfiler", EventLevel.Verbose)
+            };
+
+            var ret = IpcTraceTest.RunAndValidateEventCounts(_expectedEventCounts, _eventGeneratingAction, providers, 1024, enableRundownProvider:false);
+            if (ret < 0)
+                return ret;
+            else
+                return 100;
+        }
+
+        private static Dictionary<string, ExpectedEventCount> _expectedEventCounts = new Dictionary<string, ExpectedEventCount>()
+        {
+            { "MyEventSource", 1 },
+            { "Microsoft-DotNETCore-EventPipe", 1}
+        };
+
+        private static Action _eventGeneratingAction = () => 
+        {
+            Logger.logger.Log($"Firing an event...");
+            MyEventSource.Log.MyEvent();
+        };
+    }
+}
diff --git a/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj b/src/tests/tracing/eventpipe/simpleprovidervalidation/simpleprovidervalidation.csproj
new file mode 100644 (file)
index 0000000..34d588f
--- /dev/null
@@ -0,0 +1,17 @@
+<Project Sdk="Microsoft.NET.Sdk">
+  <PropertyGroup>
+    <TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier>
+    <OutputType>exe</OutputType>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+    <UnloadabilityIncompatible>true</UnloadabilityIncompatible>
+    <JitOptimizationSensitive>true</JitOptimizationSensitive>
+    <GCStressIncompatible>true</GCStressIncompatible>
+    <EventSourceSupport Condition="'$(TestBuildMode)' == 'nativeaot'">true</EventSourceSupport>
+    <EnableNativeEventPipe Condition="'$(TestBuildMode)' == 'nativeaot'">true</EnableNativeEventPipe>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="$(MSBuildProjectName).cs" />
+    <ProjectReference Include="../common/common.csproj" />
+    <ProjectReference Include="../common/Microsoft.Diagnostics.NETCore.Client/Microsoft.Diagnostics.NETCore.Client.csproj" />
+  </ItemGroup>
+</Project>