diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
index eb9f33319f02a..8b81b2a47da21 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets
@@ -44,6 +44,9 @@ The .NET Foundation licenses this file to you under the MIT license.
$ORIGIN
@executable_path
+
+ libeventpipe-disabled
+ libeventpipe-enabled
@@ -51,6 +54,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
index fe5cdf1cd8638..5c115640adc8d 100644
--- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
+++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Windows.targets
@@ -25,6 +25,8 @@ The .NET Foundation licenses this file to you under the MIT license.
wmainCRTStartup
WINDOWS
CONSOLE
+ eventpipe-disabled
+ eventpipe-enabled
@@ -33,6 +35,7 @@ The .NET Foundation licenses this file to you under the MIT license.
+
diff --git a/src/coreclr/nativeaot/Directory.Build.props b/src/coreclr/nativeaot/Directory.Build.props
index 275f0398185b3..337bffde726f7 100644
--- a/src/coreclr/nativeaot/Directory.Build.props
+++ b/src/coreclr/nativeaot/Directory.Build.props
@@ -65,6 +65,14 @@
FEATURE_OBJCMARSHAL;$(DefineConstants)
+
+ false
+ true
+
+
+ FEATURE_PERFTRACING;$(DefineConstants)
+
+
diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt
index 69441fd7f5881..8c80cbe2f37a0 100644
--- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt
+++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt
@@ -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
index 0000000000000..cb654d81e4c3b
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/DisabledEventPipeInterface.cpp
@@ -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
index 0000000000000..f96af50e98bd3
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/EmptyContainers.h
@@ -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
+// Assumes fHead to be false
+template
+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(reinterpret_cast(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
+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 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
index 0000000000000..44036c21cd0ef
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/EmptyContainers2.h
@@ -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
+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 ¤t;
+ }
+
+ 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
+ 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;
+
+ // 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
+ {
+ 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::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
+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
+class NoRemoveSHashTraits_EP : public PARENT
+{
+public:
+ typedef typename PARENT::element_t element_t;
+ typedef typename PARENT::count_t count_t;
+};
+
+template
+class MapSHashTraits_EP : public DefaultSHashTraits_EP< KeyValuePair_EP >
+{
+public:
+ typedef typename DefaultSHashTraits_EP< KeyValuePair_EP >::element_t element_t;
+ typedef typename DefaultSHashTraits_EP< KeyValuePair_EP >::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
index 0000000000000..a94cdd05d2d3a
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/EnabledEventPipeInterface.cpp
@@ -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
index 0000000000000..8015bc8f4c0c1
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/EventPipeInterface.h
@@ -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
diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawk.h b/src/coreclr/nativeaot/Runtime/PalRedhawk.h
index 6b14fcb2b20cc..1ffbe94c41811 100644
--- a/src/coreclr/nativeaot/Runtime/PalRedhawk.h
+++ b/src/coreclr/nativeaot/Runtime/PalRedhawk.h
@@ -716,6 +716,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
index 0000000000000..62cd5816d08fd
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/diagnosticserveradapter.h
@@ -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
+
+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
index 0000000000000..b1464bdb22570
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/disabledeventpipeinternal.cpp
@@ -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
index 0000000000000..39d658db4b18d
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/CMakeLists.txt
@@ -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 $<$,$>:/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
index 0000000000000..253f147e32d99
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/NativeaotEventPipeSupport.h
@@ -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
+
+#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
index 0000000000000..8b09c8eb16e50
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h
@@ -0,0 +1,319 @@
+// Implementation of ds-rt.h targeting AOT runtime.
+#ifndef __DIAGNOSTICS_RT_AOT_H__
+#define __DIAGNOSTICS_RT_AOT_H__
+
+#include
+
+#ifdef ENABLE_PERFTRACING
+#include "ep-rt-aot.h"
+#include
+#include
+#include
+
+#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(ds_attach_profiler_command_payload_get_profiler_guid_cref (payload)),
+ reinterpret_cast(ds_attach_profiler_command_payload_get_profiler_path (payload)),
+ reinterpret_cast(ds_attach_profiler_command_payload_get_client_data (payload)),
+ static_cast(ds_attach_profiler_command_payload_get_client_data_len (payload)),
+ static_cast(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(ds_startup_profiler_command_payload_get_profiler_guid_cref (payload)));
+ profilerData->path.Set(reinterpret_cast(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(name), reinterpret_cast(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
index 0000000000000..9c01f9f6ff016
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-types-aot.h
@@ -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
+
+#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 ds_rt_ipc_poll_handle_array_t;
+
+#undef ds_rt_ipc_poll_handle_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t ds_rt_ipc_poll_handle_array_iterator_t;
+
+/*
+ * DiagnosticsPort.
+ */
+
+#undef ds_rt_port_array_t
+typedef struct _rt_aot_array_internal_t ds_rt_port_array_t;
+
+#undef ds_rt_port_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t ds_rt_port_array_iterator_t;
+
+#undef ds_rt_port_config_array_t
+typedef struct _rt_aot_array_internal_t ds_rt_port_config_array_t;
+
+#undef ds_rt_port_config_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_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 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
index 0000000000000..ad1951fc100aa
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp
@@ -0,0 +1,502 @@
+#include
+
+#ifdef ENABLE_PERFTRACING
+#include
+#include
+#include
+#include
+
+// 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("");
+}
+
+uint32_t
+ep_rt_aot_atomic_inc_uint32_t (volatile uint32_t *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return static_cast(PalInterlockedIncrement ((volatile int32_t *)(value)));
+}
+
+uint32_t
+ep_rt_aot_atomic_dec_uint32_t (volatile uint32_t *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return static_cast(PalInterlockedDecrement ((volatile int32_t *)(value)));
+}
+
+int32_t
+ep_rt_aot_atomic_inc_int32_t (volatile int32_t *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return static_cast(PalInterlockedIncrement (value));
+}
+
+int32_t
+ep_rt_aot_atomic_dec_int32_t (volatile int32_t *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return static_cast(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(PalInterlockedCompareExchange64 ((volatile int64_t *)target, (int64_t)value, (int64_t)expected));
+#else
+ return static_cast(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(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(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(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(thread_func);
+ thread_params->thread_params = params;
+ if (!PalStartEventPipeHelperThread(reinterpret_cast(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(ns/1000000));
+}
+
+uint32_t
+ep_rt_aot_current_process_get_id (void)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return static_cast(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(0);
+#else
+ return static_cast(::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(((static_cast(value.dwHighDateTime)) << 32) | static_cast(value.dwLowDateTime));
+}
+
+uint8_t *
+ep_rt_aot_valloc0 (size_t buffer_size)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return reinterpret_cast(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(str));
+}
+
+uint32_t
+ep_rt_aot_volatile_load_uint32_t (const volatile uint32_t *ptr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return VolatileLoad ((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 ((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 *)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 *)ptr, value);
+}
+
+uint64_t
+ep_rt_aot_volatile_load_uint64_t (const volatile uint64_t *ptr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return VolatileLoad ((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 ((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 *)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 *)ptr, value);
+}
+
+int64_t
+ep_rt_aot_volatile_load_int64_t (const volatile int64_t *ptr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return VolatileLoad ((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 *)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_int64_t (
+ volatile int64_t *ptr,
+ int64_t value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ VolatileStore ((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 *)ptr, value);
+}
+
+void *
+ep_rt_aot_volatile_load_ptr (volatile void **ptr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return VolatileLoad ((void **)ptr);
+}
+
+void *
+ep_rt_aot_volatile_load_ptr_without_barrier (volatile void **ptr)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return VolatileLoadWithoutBarrier ((void **)ptr);
+}
+
+void
+ep_rt_aot_volatile_store_ptr (
+ volatile void **ptr,
+ void *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ VolatileStore ((void **)ptr, value);
+}
+
+void
+ep_rt_aot_volatile_store_ptr_without_barrier (
+ volatile void **ptr,
+ void *value)
+{
+ STATIC_CONTRACT_NOTHROW;
+ VolatileStoreWithoutBarrier ((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
index 0000000000000..5c6f8ab834dc0
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h
@@ -0,0 +1,3145 @@
+// Implementation of ep-rt.h targeting CoreCLR runtime.
+#ifndef __EVENTPIPE_RT_AOT_H__
+#define __EVENTPIPE_RT_AOT_H__
+
+#include // For isspace
+
+#include
+#ifdef ENABLE_PERFTRACING
+#include
+#include
+#include
+#include
+
+#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(val);
+ uintptr_t result = (rawVal + (alignment - 1)) & ~(alignment - 1);
+ EP_ASSERT( result >= rawVal ); // check for overflow
+ return reinterpret_cast(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
+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
+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(current->GetValue ()));
+ delete current;
+ }
+ delete list->list;
+ }
+ list->list = NULL;
+}
+
+template
+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(current->GetValue ()));
+ delete current;
+ }
+}
+
+template
+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
+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
+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
+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
+static
+inline
+bool
+_rt_aot_list_is_valid (CONST_LIST_TYPE *list)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return (list != NULL && list->list != NULL);
+}
+
+template
+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
+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
+static
+inline
+void
+_rt_aot_list_iterator_next (ITERATOR_TYPE *iterator)
+{
+ STATIC_CONTRACT_NOTHROW;
+ EP_ASSERT (iterator != NULL);
+
+ (*iterator)++;
+}
+
+template
+static
+inline
+ITEM_TYPE
+_rt_aot_list_iterator_value (CONST_ITERATOR_TYPE *iterator)
+{
+ STATIC_CONTRACT_NOTHROW;
+ EP_ASSERT (iterator != NULL);
+
+ return const_cast(iterator)->operator*();
+}
+
+template
+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
+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
+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
+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
+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
+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
+static
+inline
+bool
+_rt_aot_queue_is_valid (CONST_QUEUE_TYPE *queue)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return (queue != NULL && queue->queue != NULL);
+}
+
+template
+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
+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
+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
+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
+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
+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
+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
+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
+static
+inline
+bool
+_rt_aot_array_is_valid (CONST_ARRAY_TYPE *ep_array)
+{
+ STATIC_CONTRACT_NOTHROW;
+ return (ep_array->array != NULL);
+}
+
+template
+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
+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(iterator->array->Size ()));
+}
+
+template
+static
+inline
+void
+_rt_aot_array_iterator_next (ITERATOR_TYPE *iterator)
+{
+ STATIC_CONTRACT_NOTHROW;
+ EP_ASSERT (iterator != NULL);
+
+ iterator->index++;
+}
+
+template
+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(iterator->array->Size ()));
+
+ return iterator->array->operator[] (iterator->index);
+}
+
+template
+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(ep_array->array->Size ());
+ return temp;
+}
+
+template
+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
+static
+inline
+void
+_rt_aot_array_reverse_iterator_next (ITERATOR_TYPE *iterator)
+{
+ STATIC_CONTRACT_NOTHROW;
+ EP_ASSERT (iterator != NULL);
+
+ iterator->index--;
+}
+
+template
+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
+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
+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((ptrdiff_t)(iterator->Value ())));
+ }
+ delete hash_map->table;
+ }
+}
+
+template
+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
+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
+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((ptrdiff_t)(iterator->Value ())));
+ }
+ hash_map->table->RemoveAll ();
+}
+
+template
+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
+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
+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
+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(static_cast(ret->Value ())));
+}
+
+template
+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
+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
+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
+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
+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); \
+ } \
+ 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, 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, 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, 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, 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, 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); \
+ } \
+ 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); \
+ }
+
+#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); \
+ } \
+ 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, 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); \
+ } \
+ 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); \
+ }
+
+#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); \
+ } \
+ 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); \
+ } \
+ 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, 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, 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, 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); \
+ } \
+ 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); \
+ }
+
+#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(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(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(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 (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 (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 (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 (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 (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(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 (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 (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); \
+ } \
+ 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); \
+ }
+
+#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 (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 (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); \
+ } \
+ 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); \
+ }
+
+#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, 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); \
+ } \
+ 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, 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); \
+ } \
+ 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, 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); \
+ } \
+ 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); \
+ }
+
+#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, 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, 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); \
+ } \
+ 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, 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(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(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(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("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> *provider_list = list->list;
+ SListElem_EP *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(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> *provider_list = list->list;
+ EventPipeSessionProvider *session_provider = NULL;
+ SListElem_EP *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(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(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(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(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(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(str1), reinterpret_cast(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(str1), reinterpret_cast(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(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(str), static_cast(str_len), reinterpret_cast(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(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(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(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(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(::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(thread_id);
+}
+
+static
+inline
+ep_rt_thread_id_t
+ep_rt_uint64_t_to_thread_id_t (uint64_t thread_id)
+{
+ return static_cast(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(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(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
index 0000000000000..d42cad689d5e5
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-config-aot.h
@@ -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
index 0000000000000..9aa547e6b4f4c
--- /dev/null
+++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-types-aot.h
@@ -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
+
+#include
+
+#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
+struct _rt_aot_list_internal_t {
+ typedef struct SListElem_EP element_type_t;
+ typedef class SList_EP list_type_t;
+ list_type_t *list;
+};
+
+template
+struct _rt_aot_queue_internal_t {
+ typedef struct SListElem_EP element_type_t;
+ typedef class SList_EP queue_type_t;
+ queue_type_t *queue;
+};
+
+template
+struct _rt_aot_array_internal_t {
+ typedef T element_type_t;
+ typedef class CQuickArrayList_EP array_type_t;
+ array_type_t *array;
+};
+
+template
+struct _rt_aot_array_iterator_internal_t {
+ typedef typename _rt_aot_array_internal_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
+struct _rt_aot_table_default_internal_t {
+ typedef class SHash_EP > > table_type_t;
+ rt_aot_table_callbacks_t callbacks;
+ table_type_t *table;
+};
+
+template
+struct _rt_aot_table_remove_internal_t {
+ typedef class SHash_EP< MapSHashTraits_EP > table_type_t;
+ rt_aot_table_callbacks_t callbacks;
+ table_type_t *table;
+};
+
+class EventPipeAotStackHashTraits : public NoRemoveSHashTraits_EP< MapSHashTraits_EP >
+{
+public:
+ typedef typename MapSHashTraits_EP::element_t element_t;
+ typedef typename MapSHashTraits_EP::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
+struct _rt_aot_table_custom_internal_t {
+ typedef class SHash_EP 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 ep_rt_buffer_array_t;
+
+#undef ep_rt_buffer_array_iterator_t
+typedef struct _rt_aot_array_iterator_internal_t