amd64: fix multithread, fix vgui, fix physmodels

This commit is contained in:
nillerusr
2022-06-05 01:44:42 +03:00
parent 01413fdd71
commit 9ee21ecf90
63 changed files with 5679 additions and 2468 deletions
+170 -83
View File
@@ -1,4 +1,4 @@
//========= Copyright Valve Corporation, All rights reserved. ============//
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Defines a symbol table
//
@@ -9,29 +9,11 @@
#pragma warning (disable:4514)
#include "utlsymbol.h"
#include "KeyValues.h"
#include "tier0/threadtools.h"
#include "tier0/memdbgon.h"
#include "stringpool.h"
#include "utlhashtable.h"
#include "utlstring.h"
// Ensure that everybody has the right compiler version installed. The version
// number can be obtained by looking at the compiler output when you type 'cl'
// and removing the last two digits and the periods: 16.00.40219.01 becomes 160040219
#ifdef _MSC_FULL_VER
#if _MSC_FULL_VER > 160000000
// VS 2010
#if _MSC_FULL_VER < 160040219
#error You must install VS 2010 SP1
#endif
#else
// VS 2005
#if _MSC_FULL_VER < 140050727
#error You must install VS 2005 SP1
#endif
#endif
#endif
#include "generichash.h"
#include "tier0/vprof.h"
#include <stddef.h>
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
@@ -68,6 +50,17 @@ void CUtlSymbol::Initialize()
}
}
void CUtlSymbol::LockTableForRead()
{
Initialize();
s_pSymbolTable->LockForRead();
}
void CUtlSymbol::UnlockTableForRead()
{
s_pSymbolTable->UnlockForRead();
}
//-----------------------------------------------------------------------------
// Purpose: Singleton to delete table on exit from module
//-----------------------------------------------------------------------------
@@ -104,6 +97,11 @@ const char* CUtlSymbol::String( ) const
return CurrTable()->String(m_Id);
}
const char* CUtlSymbol::StringNoLock( ) const
{
return CurrTable()->StringNoLock(m_Id);
}
void CUtlSymbol::DisableStaticSymbolTable()
{
s_bAllowStaticSymbolTable = false;
@@ -125,16 +123,25 @@ bool CUtlSymbol::operator==( const char* pStr ) const
//-----------------------------------------------------------------------------
// symbol table stuff
//-----------------------------------------------------------------------------
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
inline const char* CUtlSymbolTable::DecoratedStringFromIndex( const CStringPoolIndex &index ) const
{
Assert( index.m_iPool < m_StringPools.Count() );
Assert( index.m_iOffset < m_StringPools[index.m_iPool]->m_TotalLen );
return &m_StringPools[index.m_iPool]->m_Data[index.m_iOffset];
// step over the hash decorating the beginning of the string
return (&m_StringPools[index.m_iPool]->m_Data[index.m_iOffset]);
}
inline const char* CUtlSymbolTable::StringFromIndex( const CStringPoolIndex &index ) const
{
// step over the hash decorating the beginning of the string
return DecoratedStringFromIndex(index)+sizeof(hashDecoration_t);
}
// The first two bytes of each string in the pool are actually the hash for that string.
// Thus we compare hashes rather than entire strings for a significant perf benefit.
// However since there is a high rate of hash collision we must still compare strings
// if the hashes match.
bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStringPoolIndex &i2 ) const
{
// Need to do pointer math because CUtlSymbolTable is used in CUtlVectors, and hence
@@ -142,21 +149,79 @@ bool CUtlSymbolTable::CLess::operator()( const CStringPoolIndex &i1, const CStri
// right now at least, because m_LessFunc is the first member of CUtlRBTree, and m_Lookup
// is the first member of CUtlSymbolTabke, this == pTable
CUtlSymbolTable *pTable = (CUtlSymbolTable *)( (byte *)this - offsetof(CUtlSymbolTable::CTree, m_LessFunc) ) - offsetof(CUtlSymbolTable, m_Lookup );
#if 1 // using the hashes
const char *str1, *str2;
hashDecoration_t hash1, hash2;
if (i1 == INVALID_STRING_INDEX)
{
str1 = pTable->m_pUserSearchString;
hash1 = pTable->m_nUserSearchStringHash;
}
else
{
str1 = pTable->DecoratedStringFromIndex( i1 );
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str1);
str1 += sizeof(hashDecoration_t);
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str1) : HashStringCaseless(str1) ),
"The stored hash (%d) for symbol %s is not correct.", storedHash, str1 );
hash1 = storedHash;
}
if (i2 == INVALID_STRING_INDEX)
{
str2 = pTable->m_pUserSearchString;
hash2 = pTable->m_nUserSearchStringHash;
}
else
{
str2 = pTable->DecoratedStringFromIndex( i2 );
hashDecoration_t storedHash = *reinterpret_cast<const hashDecoration_t *>(str2);
str2 += sizeof(hashDecoration_t);
AssertMsg2( storedHash == ( !pTable->m_bInsensitive ? HashString(str2) : HashStringCaseless(str2) ),
"The stored hash (%d) for symbol '%s' is not correct.", storedHash, str2 );
hash2 = storedHash;
}
// compare the hashes
if ( hash1 == hash2 )
{
if ( !str1 && str2 )
return 1;
if ( !str2 && str1 )
return -1;
if ( !str1 && !str2 )
return 0;
// if the hashes match compare the strings
if ( !pTable->m_bInsensitive )
return strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
}
else
{
return hash1 < hash2;
}
#else // not using the hashes, just comparing strings
const char* str1 = (i1 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i1 );
pTable->StringFromIndex( i1 );
const char* str2 = (i2 == INVALID_STRING_INDEX) ? pTable->m_pUserSearchString :
pTable->StringFromIndex( i2 );
pTable->StringFromIndex( i2 );
if ( !str1 && str2 )
return false;
return 1;
if ( !str2 && str1 )
return true;
return -1;
if ( !str1 && !str2 )
return false;
return 0;
if ( !pTable->m_bInsensitive )
return V_strcmp( str1, str2 ) < 0;
return strcmp( str1, str2 ) < 0;
else
return V_stricmp( str1, str2 ) < 0;
return strcmpi( str1, str2 ) < 0;
#endif
}
@@ -177,11 +242,13 @@ CUtlSymbolTable::~CUtlSymbolTable()
CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
{
VPROF( "CUtlSymbol::Find" );
if (!pString)
return CUtlSymbol();
// Store a special context used to help with insertion
m_pUserSearchString = pString;
m_nUserSearchStringHash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
// Passing this special invalid symbol makes the comparison function
// use the string passed in the context
@@ -189,6 +256,7 @@ CUtlSymbol CUtlSymbolTable::Find( const char* pString ) const
#ifdef _DEBUG
m_pUserSearchString = NULL;
m_nUserSearchStringHash = 0;
#endif
return CUtlSymbol( idx );
@@ -217,6 +285,7 @@ int CUtlSymbolTable::FindPoolWithSpace( int len ) const
CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
{
VPROF("CUtlSymbol::AddString");
if (!pString)
return CUtlSymbol( UTL_INVAL_SYMBOL );
@@ -225,35 +294,47 @@ CUtlSymbol CUtlSymbolTable::AddString( const char* pString )
if (id.IsValid())
return id;
int len = V_strlen(pString) + 1;
int lenString = strlen(pString) + 1; // length of just the string
int lenDecorated = lenString + sizeof(hashDecoration_t); // and with its hash decoration
// make sure that all strings are aligned on 2-byte boundaries so the hashes will read correctly
COMPILE_TIME_ASSERT(sizeof(hashDecoration_t) == 2);
lenDecorated = (lenDecorated + 1) & (~0x01); // round up to nearest multiple of 2
// Find a pool with space for this string, or allocate a new one.
int iPool = FindPoolWithSpace( len );
int iPool = FindPoolWithSpace( lenDecorated );
if ( iPool == -1 )
{
// Add a new pool.
int newPoolSize = max( len, MIN_STRING_POOL_SIZE );
StringPool_t *pPool = (StringPool_t*)malloc( sizeof( StringPool_t ) + newPoolSize - 1 );
pPool->m_TotalLen = newPoolSize;
int newPoolSize = MAX( lenDecorated + sizeof( StringPool_t ), MIN_STRING_POOL_SIZE );
StringPool_t *pPool = (StringPool_t*)malloc( newPoolSize );
pPool->m_TotalLen = newPoolSize - sizeof( StringPool_t );
pPool->m_SpaceUsed = 0;
iPool = m_StringPools.AddToTail( pPool );
}
// Compute a hash
hashDecoration_t hash = m_bInsensitive ? HashStringCaseless(pString) : HashString(pString) ;
// Copy the string in.
StringPool_t *pPool = m_StringPools[iPool];
Assert( pPool->m_SpaceUsed < 0xFFFF ); // This should never happen, because if we had a string > 64k, it
// would have been given its entire own pool.
unsigned short iStringOffset = pPool->m_SpaceUsed;
const char *startingAddr = &pPool->m_Data[pPool->m_SpaceUsed];
memcpy( &pPool->m_Data[pPool->m_SpaceUsed], pString, len );
pPool->m_SpaceUsed += len;
// store the hash at the head of the string
*((hashDecoration_t *)(startingAddr)) = hash;
// and then the string's data
memcpy( (void *)(startingAddr + sizeof(hashDecoration_t)), pString, lenString );
pPool->m_SpaceUsed += lenDecorated;
// didn't find, insert the string into the vector.
// insert the string into the vector.
CStringPoolIndex index;
index.m_iPool = iPool;
index.m_iOffset = iStringOffset;
MEM_ALLOC_CREDIT();
UtlSymId_t idx = m_Lookup.Insert( index );
return CUtlSymbol( idx );
}
@@ -288,22 +369,6 @@ void CUtlSymbolTable::RemoveAll()
}
class CUtlFilenameSymbolTable::HashTable : public CUtlStableHashtable<CUtlConstString>
{
};
CUtlFilenameSymbolTable::CUtlFilenameSymbolTable()
{
m_Strings = new HashTable;
}
CUtlFilenameSymbolTable::~CUtlFilenameSymbolTable()
{
delete m_Strings;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pFileName -
@@ -328,7 +393,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
strlwr( fn );
#endif
// Split the filename into constituent parts
@@ -340,20 +405,18 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindOrAddFileName( const char *pFileNa
// not found, lock and look again
FileNameHandleInternal_t handle;
m_lock.LockForWrite();
handle.path = m_Strings->Insert( basepath ) + 1;
handle.file = m_Strings->Insert( filename ) + 1;
//handle.path = m_StringPool.FindStringHandle( basepath );
//handle.file = m_StringPool.FindStringHandle( filename );
//if ( handle.path != m_Strings.InvalidHandle() && handle.file )
//{
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
if ( handle.GetPath() && handle.GetFile() )
{
// found
// m_lock.UnlockWrite();
// return *( FileNameHandle_t * )( &handle );
//}
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
}
// safely add it
//handle.path = m_StringPool.ReferenceStringHandle( basepath );
//handle.file = m_StringPool.ReferenceStringHandle( filename );
handle.SetPath( m_PathStringPool.ReferenceStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.ReferenceStringHandle( filename ) );
m_lock.UnlockWrite();
return *( FileNameHandle_t * )( &handle );
@@ -371,7 +434,7 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
Q_strncpy( fn, pFileName, sizeof( fn ) );
Q_RemoveDotSlashes( fn );
#ifdef _WIN32
Q_strlower( fn );
strlwr( fn );
#endif
// Split the filename into constituent parts
@@ -382,16 +445,13 @@ FileNameHandle_t CUtlFilenameSymbolTable::FindFileName( const char *pFileName )
FileNameHandleInternal_t handle;
Assert( (uint16)(m_Strings->InvalidHandle() + 1) == 0 );
m_lock.LockForRead();
handle.path = m_Strings->Find(basepath) + 1;
handle.file = m_Strings->Find(filename) + 1;
//handle.path = m_StringPool.FindStringHandle(basepath);
//handle.file = m_StringPool.FindStringHandle(filename);
handle.SetPath( m_PathStringPool.FindStringHandle( basepath ) );
handle.SetFile( m_FileStringPool.FindStringHandle( filename ) );
m_lock.UnlockRead();
if ( handle.path == 0 || handle.file == 0 )
if ( ( handle.GetPath() == 0 ) || ( handle.GetFile() == 0 ) )
return NULL;
return *( FileNameHandle_t * )( &handle );
@@ -406,17 +466,15 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
{
buf[ 0 ] = 0;
FileNameHandleInternal_t *internal = ( FileNameHandleInternal_t * )&handle;
if ( !internal || !internal->file || !internal->path )
FileNameHandleInternal_t *internalFileHandle = ( FileNameHandleInternal_t * )&handle;
if ( !internalFileHandle )
{
return false;
}
m_lock.LockForRead();
//const char *path = m_StringPool.HandleToString(internal->path);
//const char *fn = m_StringPool.HandleToString(internal->file);
const char *path = (*m_Strings)[ internal->path - 1 ].Get();
const char *fn = (*m_Strings)[ internal->file - 1].Get();
const char *path = m_PathStringPool.HandleToString( internalFileHandle->GetPath() );
const char *fn = m_FileStringPool.HandleToString( internalFileHandle->GetFile() );
m_lock.UnlockRead();
if ( !path || !fn )
@@ -432,5 +490,34 @@ bool CUtlFilenameSymbolTable::String( const FileNameHandle_t& handle, char *buf,
void CUtlFilenameSymbolTable::RemoveAll()
{
m_Strings->Purge();
m_PathStringPool.FreeAll();
m_FileStringPool.FreeAll();
}
void CUtlFilenameSymbolTable::SpewStrings()
{
m_lock.LockForRead();
m_PathStringPool.SpewStrings();
m_FileStringPool.SpewStrings();
m_lock.UnlockRead();
}
bool CUtlFilenameSymbolTable::SaveToBuffer( CUtlBuffer &buffer )
{
m_lock.LockForRead();
bool bResult = m_PathStringPool.SaveToBuffer( buffer );
bResult = bResult && m_FileStringPool.SaveToBuffer( buffer );
m_lock.UnlockRead();
return bResult;
}
bool CUtlFilenameSymbolTable::RestoreFromBuffer( CUtlBuffer &buffer )
{
m_lock.LockForWrite();
bool bResult = m_PathStringPool.RestoreFromBuffer( buffer );
bResult = bResult && m_FileStringPool.RestoreFromBuffer( buffer );
m_lock.UnlockWrite();
return bResult;
}