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