Adding support for ASan (Windows/MSVC) and fixing AzCore

This commit is contained in:
Esteban Papp
2021-08-19 14:17:14 -07:00
committed by GitHub
40 changed files with 368 additions and 276 deletions
@@ -13,6 +13,7 @@
#include <AzCore/RTTI/TypeInfoSimple.h>
#include <AzCore/std/limits.h>
#include <AzCore/std/string/string_view.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ::Debug
{
@@ -12,6 +12,7 @@
#include <AzCore/Math/MathUtils.h>
#include <AzCore/std/typetraits/is_const.h>
#include <AzCore/std/typetraits/has_member_function.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ
{
@@ -11,6 +11,7 @@
#include <AzCore/IO/SystemFile.h>
#include <AzCore/IO/IOUtils.h>
#include <AzCore/std/algorithm.h>
#include <AzCore/Casting/numeric_cast.h>
namespace AZ::IO
{
@@ -10,6 +10,7 @@
#include <AzCore/std/containers/array.h>
#include <AzCore/std/string/wildcard.h>
#include <AzCore/Casting/numeric_cast.h>
// extern instantiations of Path templates to prevent implicit instantiations
namespace AZ::IO
@@ -17,15 +17,23 @@
#include <AzCore/Debug/Profiler.h>
#define AZCORE_SYS_ALLOCATOR_HPPA // If you disable this make sure you start building the heapschema.cpp
//#define AZCORE_SYS_ALLOCATOR_MALLOC
#define AZCORE_SYSTEM_ALLOCATOR_HPHA 1
#define AZCORE_SYSTEM_ALLOCATOR_MALLOC 2
#define AZCORE_SYSTEM_ALLOCATOR_HEAP 3
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
# include <AzCore/Memory/HphaSchema.h>
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
#include <AzCore/Memory/MallocSchema.h>
#if !defined(AZCORE_SYSTEM_ALLOCATOR)
// define the default
#define AZCORE_SYSTEM_ALLOCATOR AZCORE_SYSTEM_ALLOCATOR_HPHA
#endif
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
#include <AzCore/Memory/HphaSchema.h>
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
#include <AzCore/Memory/MallocSchema.h>
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
#include <AzCore/Memory/HeapSchema.h>
#else
# include <AzCore/Memory/HeapSchema.h>
#error "Invalid allocator selected for SystemAllocator"
#endif
@@ -34,12 +42,12 @@ using namespace AZ;
//////////////////////////////////////////////////////////////////////////
// Globals - we use global storage for the first memory schema, since we can't use dynamic memory!
static bool g_isSystemSchemaUsed = false;
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
static AZStd::aligned_storage<sizeof(HphaSchema), AZStd::alignment_of<HphaSchema>::value>::type g_systemSchema;
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
static AZStd::aligned_storage<sizeof(MallocSchema), AZStd::alignment_of<MallocSchema>::value>::type g_systemSchema;
#else
static AZStd::aligned_storage<sizeof(HeapSchema), AZStd::alignment_of<HeapSchema>::value>::type g_systemSchema;
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
static AZStd::aligned_storage<sizeof(HphaSchema), AZStd::alignment_of<HphaSchema>::value>::type g_systemSchema;
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
static AZStd::aligned_storage<sizeof(MallocSchema), AZStd::alignment_of<MallocSchema>::value>::type g_systemSchema;
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
static AZStd::aligned_storage<sizeof(HeapSchema), AZStd::alignment_of<HeapSchema>::value>::type g_systemSchema;
#endif
//////////////////////////////////////////////////////////////////////////
@@ -97,9 +105,9 @@ SystemAllocator::Create(const Descriptor& desc)
else
{
m_isCustom = false;
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
HphaSchema::Descriptor heapDesc;
heapDesc.m_pageSize = desc.m_heap.m_pageSize;
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
HphaSchema::Descriptor heapDesc;
heapDesc.m_pageSize = desc.m_heap.m_pageSize;
heapDesc.m_poolPageSize = desc.m_heap.m_poolPageSize;
AZ_Assert(desc.m_heap.m_numFixedMemoryBlocks <= 1, "We support max1 memory block at the moment!");
if (desc.m_heap.m_numFixedMemoryBlocks > 0)
@@ -111,11 +119,10 @@ SystemAllocator::Create(const Descriptor& desc)
heapDesc.m_isPoolAllocations = desc.m_heap.m_isPoolAllocations;
// Fix SystemAllocator from growing in small chunks
heapDesc.m_systemChunkSize = desc.m_heap.m_systemChunkSize;
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
MallocSchema::Descriptor heapDesc;
#else
HeapSchema::Descriptor heapDesc;
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
HeapSchema::Descriptor heapDesc;
memcpy(heapDesc.m_memoryBlocks, desc.m_heap.m_memoryBlocks, sizeof(heapDesc.m_memoryBlocks));
memcpy(heapDesc.m_memoryBlocksByteSize, desc.m_heap.m_memoryBlocksByteSize, sizeof(heapDesc.m_memoryBlocksByteSize));
heapDesc.m_numMemoryBlocks = desc.m_heap.m_numMemoryBlocks;
@@ -124,11 +131,11 @@ SystemAllocator::Create(const Descriptor& desc)
{
AZ_Assert(!g_isSystemSchemaUsed, "AZ::SystemAllocator MUST be created first! It's the source of all allocations!");
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
m_allocator = new(&g_systemSchema)HphaSchema(heapDesc);
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
m_allocator = new(&g_systemSchema)MallocSchema(heapDesc);
#else
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
m_allocator = new(&g_systemSchema)HeapSchema(heapDesc);
#endif
g_isSystemSchemaUsed = true;
@@ -139,14 +146,13 @@ SystemAllocator::Create(const Descriptor& desc)
// this class should be inheriting from SystemAllocator
AZ_Assert(AllocatorInstance<SystemAllocator>::IsReady(), "System allocator must be created before any other allocator! They allocate from it.");
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
m_allocator = azcreate(HphaSchema, (heapDesc), SystemAllocator);
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
m_allocator = azcreate(MallocSchema, (heapDesc), SystemAllocator);
#else
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
m_allocator = azcreate(HeapSchema, (heapDesc), SystemAllocator);
#endif
if (m_allocator == NULL)
{
isReady = false;
@@ -178,11 +184,11 @@ SystemAllocator::Destroy()
{
if ((void*)m_allocator == (void*)&g_systemSchema)
{
#ifdef AZCORE_SYS_ALLOCATOR_HPPA
#if AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HPHA
static_cast<HphaSchema*>(m_allocator)->~HphaSchema();
#elif defined(AZCORE_SYS_ALLOCATOR_MALLOC)
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_MALLOC
static_cast<MallocSchema*>(m_allocator)->~MallocSchema();
#else
#elif AZCORE_SYSTEM_ALLOCATOR == AZCORE_SYSTEM_ALLOCATOR_HEAP
static_cast<HeapSchema*>(m_allocator)->~HeapSchema();
#endif
g_isSystemSchemaUsed = false;
@@ -36,10 +36,13 @@ namespace AZ
void NameData::release()
{
// this could be released after we decrement the counter, therefore we will
// base the release on the hash which is stable
Hash hash = m_hash;
AZ_Assert(m_useCount > 0, "m_useCount is already 0!");
if (m_useCount.fetch_sub(1) == 1)
{
AZ::NameDictionary::Instance().TryReleaseName(this);
AZ::NameDictionary::Instance().TryReleaseName(hash);
}
}
}
+6
View File
@@ -10,6 +10,11 @@
#include <AzCore/Name/Internal/NameData.h>
namespace UnitTest
{
class NameTest;
}
namespace AZ
{
class NameDictionary;
@@ -29,6 +34,7 @@ namespace AZ
class Name
{
friend NameDictionary;
friend UnitTest::NameTest;
public:
using Hash = Internal::NameData::Hash;
@@ -166,7 +166,7 @@ namespace AZ
}
}
void NameDictionary::TryReleaseName(Internal::NameData* nameData)
void NameDictionary::TryReleaseName(Name::Hash hash)
{
// Note that we don't remove NameData from the dictionary if it has been involved in a collision.
// This avoids specific edge cases where a Name object could get an incorrect hash value. Consider
@@ -179,15 +179,24 @@ namespace AZ
// the dictionary *again*, this time with hash value 1000. Name objects pointing to the original
// entry and Name objects pointing to the new entry will fail comparison operations.
// Early exit to avoid locking the mutex unnecessarily.
if (nameData->m_hashCollision)
{
return;
}
AZStd::unique_lock<AZStd::shared_mutex> lock(m_sharedMutex);
// Check m_hashCollision again inside the m_sharedMutex because a new collision could have happened
auto dictIt = m_dictionary.find(hash);
if (dictIt == m_dictionary.end())
{
// This check is to safeguard around the following scenario
// T1, gets into TryReleaseName
// T2 gets into MakeName, acquires the lock, returns a new Name that increments the counter
// T2 deletes the Name decrements the counter, gets into TryReleaseName
// T1 gets the lock, goes to the compare_exchange if and has a counter of 0, deletes
// Then T2 continues, gets the lock and crashes because nameData was deleted
return;
}
Internal::NameData* nameData = dictIt->second;
// Check m_hashCollision inside the m_sharedMutex because a new collision could have happened
// on another thread before taking the lock.
if (nameData->m_hashCollision)
{
@@ -83,7 +83,7 @@ namespace AZ
// Attempts to release the name from the dictionary, but checks to make sure
// a reference wasn't taken by another thread.
void TryReleaseName(Internal::NameData* data);
void TryReleaseName(Name::Hash hash);
//////////////////////////////////////////////////////////////////////////
@@ -7,7 +7,6 @@
*/
#pragma once
#include <AzCore/Casting/numeric_cast.h>
#include <AzCore/std/createdestroy.h>
#include <AzCore/std/iterator.h>
@@ -46,6 +45,10 @@ namespace AZStd
return npos;
}
size_t foundIndex = searchIndex + charFindIndex;
if (foundIndex + count > size)
{
return npos; // the rest of the string doesnt fit in the remainder of the data buffer
}
if (Traits::compare(&data[foundIndex], ptr, count) == 0)
{
return foundIndex;