diff options
Diffstat (limited to 'mp/src/public/tier0')
| -rw-r--r-- | mp/src/public/tier0/dbg.h | 12 | ||||
| -rw-r--r-- | mp/src/public/tier0/minidump.h | 19 | ||||
| -rw-r--r-- | mp/src/public/tier0/platform.h | 61 | ||||
| -rw-r--r-- | mp/src/public/tier0/stacktools.h | 153 | ||||
| -rw-r--r-- | mp/src/public/tier0/threadtools.h | 63 | ||||
| -rw-r--r-- | mp/src/public/tier0/vprof.h | 2 | ||||
| -rw-r--r-- | mp/src/public/tier0/vprof_telemetry.h | 2 | ||||
| -rw-r--r-- | mp/src/public/tier0/wchartypes.h | 8 |
8 files changed, 305 insertions, 15 deletions
diff --git a/mp/src/public/tier0/dbg.h b/mp/src/public/tier0/dbg.h index c35e7a67..5fa68adf 100644 --- a/mp/src/public/tier0/dbg.h +++ b/mp/src/public/tier0/dbg.h @@ -221,6 +221,9 @@ typedef void (*AssertFailedNotifyFunc_t)( const char *pchFile, int nLine, const DBG_INTERFACE void SetAssertFailedNotifyFunc( AssertFailedNotifyFunc_t func ); DBG_INTERFACE void CallAssertFailedNotifyFunc( const char *pchFile, int nLine, const char *pchMessage ); +/* True if -hushasserts was passed on command line. */ +DBG_INTERFACE bool HushAsserts(); + #if defined( USE_SDL ) DBG_INTERFACE void SetAssertDialogParent( struct SDL_Window *window ); DBG_INTERFACE struct SDL_Window * GetAssertDialogParent(); @@ -412,12 +415,15 @@ DBG_INTERFACE struct SDL_Window * GetAssertDialogParent(); /* These are always compiled in */ DBG_INTERFACE void Msg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DMsg( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); DBG_INTERFACE void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DWarning( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); DBG_INTERFACE void Log( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 ); +DBG_INTERFACE void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); #ifdef Error // p4.cpp does a #define Error Warning and in that case the Error prototype needs to @@ -425,17 +431,23 @@ DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRIN DBG_INTERFACE void Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); #else DBG_INTERFACE void NORETURN Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 ); +DBG_INTERFACE void NORETURN ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ); + #endif #else inline void Msg( ... ) {} inline void DMsg( ... ) {} +inline void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) {} +inline void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void DWarning( ... ) {} inline void Log( ... ) {} inline void DLog( ... ) {} +inline void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} inline void Error( ... ) {} +inline void ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {} #endif diff --git a/mp/src/public/tier0/minidump.h b/mp/src/public/tier0/minidump.h index fad2d073..e6507256 100644 --- a/mp/src/public/tier0/minidump.h +++ b/mp/src/public/tier0/minidump.h @@ -82,6 +82,23 @@ PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction( FnMiniDump pfn ); // being silently swallowed. We should always call this at startup. PLATFORM_INTERFACE void EnableCrashingOnCrashes(); -#endif +#endif // defined(_WIN32) && !defined(_X360) + +// +// Minidump User Stream Info Comments. +// +// There currently is a single header string, and an array of 64 comment strings. +// MinidumpUserStreamInfoSetHeader() will set the single header string. +// MinidumpUserStreamInfoAppend() will round robin through and array and set the comment strings, overwriting old. +PLATFORM_INTERFACE void MinidumpUserStreamInfoSetHeader( const char *pFormat, ... ); +PLATFORM_INTERFACE void MinidumpUserStreamInfoAppend( const char *pFormat, ... ); + +// Retrieve the StreamInfo strings. +// Index 0: header string +// Index 1..: comment string +// Returns NULL when you've reached the end of the comment string array +// Empty strings ("\0") can be returned if comment hasn't been set +PLATFORM_INTERFACE const char *MinidumpUserStreamInfoGet( int Index ); #endif // MINIDUMP_H + diff --git a/mp/src/public/tier0/platform.h b/mp/src/public/tier0/platform.h index 389ab5b8..652c27c0 100644 --- a/mp/src/public/tier0/platform.h +++ b/mp/src/public/tier0/platform.h @@ -9,6 +9,18 @@ #ifndef PLATFORM_H #define PLATFORM_H +#if defined(__x86_64__) || defined(_WIN64) +#define PLATFORM_64BITS 1 +#endif + +#if defined(__GCC__) || defined(__GNUC__) +#define COMPILER_GCC 1 +#endif + +#ifdef __clang__ +#define COMPILER_CLANG 1 +#endif + #if defined( _X360 ) #define NO_STEAM #define NO_VOICE @@ -51,14 +63,13 @@ // need this for _alloca #include <alloca.h> #include <unistd.h> - #include <signal.h> +#include <signal.h> #include <time.h> #endif #include <malloc.h> #include <new> - // need this for memset #include <string.h> @@ -148,10 +159,6 @@ typedef unsigned char uint8; typedef signed char int8; -#if defined(__x86_64__) || defined(_WIN64) - #define X64BITS -#endif // __x86_64__ - #if defined( _WIN32 ) typedef __int16 int16; @@ -191,7 +198,7 @@ typedef signed char int8; typedef unsigned int uint32; typedef long long int64; typedef unsigned long long uint64; - #ifdef X64BITS + #ifdef PLATFORM_64BITS typedef long long intp; typedef unsigned long long uintp; #else @@ -202,17 +209,39 @@ typedef signed char int8; // Avoid redefinition warnings if a previous header defines this. #undef OVERRIDE - #if defined(__clang__) + #if __cplusplus >= 201103L #define OVERRIDE override - // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions] - // Disabling this warning is less intrusive than enabling C++11 extensions - #pragma GCC diagnostic ignored "-Wc++11-extensions" + #if defined(__clang__) + // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions] + // Disabling this warning is less intrusive than enabling C++11 extensions + #pragma GCC diagnostic ignored "-Wc++11-extensions" + #endif #else #define OVERRIDE #endif #endif // else _WIN32 +//----------------------------------------------------------------------------- +// Set up platform type defines. +//----------------------------------------------------------------------------- +#if defined( PLATFORM_X360 ) || defined( _PS3 ) + #if !defined( _GAMECONSOLE ) + #define _GAMECONSOLE + #endif + #define IsPC() false + #define IsGameConsole() true +#else + #define IsPC() true + #define IsGameConsole() false +#endif + +#ifdef PLATFORM_64BITS + #define IsPlatform64Bits() true +#else + #define IsPlatform64Bits() false +#endif + // From steam/steamtypes.h // RTime32 // We use this 32 bit time representing real world time. @@ -407,6 +436,13 @@ typedef void * HINSTANCE; #define DebuggerBreakIfDebugging_StagingOnly() #endif +// Allows you to specify code that should only execute if we are in a staging build. Otherwise the code noops. +#ifdef STAGING_ONLY +#define STAGING_ONLY_EXEC( _exec ) do { _exec; } while (0) +#else +#define STAGING_ONLY_EXEC( _exec ) do { } while (0) +#endif + // C functions for external declarations that call the appropriate C++ methods #ifndef EXPORT #ifdef _WIN32 @@ -1177,6 +1213,9 @@ struct CPUInformation tchar* m_szProcessorID; // Processor vendor Identification. + uint32 m_nModel; + uint32 m_nFeatures[3]; + CPUInformation(): m_Size(0){} }; diff --git a/mp/src/public/tier0/stacktools.h b/mp/src/public/tier0/stacktools.h new file mode 100644 index 00000000..c356b8c0 --- /dev/null +++ b/mp/src/public/tier0/stacktools.h @@ -0,0 +1,153 @@ +//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============// +// +// Purpose: Tools for grabbing/dumping the stack at runtime +// +// $NoKeywords: $ +//=============================================================================// + +#ifndef TIER0_STACKTOOLS_H +#define TIER0_STACKTOOLS_H + +#ifdef _WIN32 +#pragma once +#endif + +#include "tier0/platform.h" + +#if (defined( PLATFORM_WINDOWS ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT ) && defined( TCHAR_IS_CHAR ) //designed for windows/x360, not built/tested with wide characters, not intended for release builds (but probably wouldn't damage anything) +# define ENABLE_RUNTIME_STACK_TRANSLATION //uncomment to enable runtime stack translation tools. All of which use on-demand loading of necessary dll's and pdb's +#endif + +#if defined( ENABLE_RUNTIME_STACK_TRANSLATION ) +//#define ENABLE_THREAD_PARENT_STACK_TRACING 1 //uncomment to actually enable tracking stack traces from threads and jobs to their parent thread. Must also define THREAD_PARENT_STACK_TRACE_SUPPORTED in threadtools.h +# if defined( ENABLE_THREAD_PARENT_STACK_TRACING ) +# define THREAD_PARENT_STACK_TRACE_LENGTH 32 +# endif +#endif + + + + +PLATFORM_INTERFACE int GetCallStack( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +//ONLY WORKS IF THE CRAWLED PORTION OF THE STACK DISABLES FRAME POINTER OMISSION (/Oy-) "vpc /nofpo" +PLATFORM_INTERFACE int GetCallStack_Fast( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +typedef int (*FN_GetCallStack)( void **pReturnAddressesOut, int iArrayCount, int iSkipCount ); + +//where we'll find our PDB's for win32. +PLATFORM_INTERFACE void SetStackTranslationSymbolSearchPath( const char *szSemicolonSeparatedList = NULL ); +PLATFORM_INTERFACE void StackToolsNotify_LoadedLibrary( const char *szLibName ); + +//maximum output sample "tier0.dll!TranslateStackInfo - u:\Dev\L4D\src\tier0\stacktools.cpp(162) + 4 bytes" +enum TranslateStackInfo_StyleFlags_t +{ + TSISTYLEFLAG_NONE = 0, + TSISTYLEFLAG_MODULENAME = (1<<0), //start with module Sample: "tier0.dll!" + TSISTYLEFLAG_SYMBOLNAME = (1<<1), //include the symbol name Sample: "TranslateStackInfo" + TSISTYLEFLAG_FULLPATH = (1<<2), //include full path Sample: "u:\Dev\L4D\src\tier0\stacktools.cpp" + TSISTYLEFLAG_SHORTPATH = (1<<3), //only include 2 directories Sample: "\src\tier0\stacktools.cpp" + TSISTYLEFLAG_LINE = (1<<4), //file line number Sample: "(162)" + TSISTYLEFLAG_LINEANDOFFSET = (1<<5), //file line + offset Sample: "(162) + 4 bytes" + TSISTYLEFLAG_LAST = TSISTYLEFLAG_LINEANDOFFSET, + TSISTYLEFLAG_DEFAULT = (TSISTYLEFLAG_MODULENAME | TSISTYLEFLAG_SYMBOLNAME | TSISTYLEFLAG_FULLPATH | TSISTYLEFLAG_LINEANDOFFSET), //produces sample above +}; + +//Generates a formatted list of function information, returns number of translated entries +//On 360 this generates a string that can be decoded by VXConsole in print functions. Optimal path for translation because it's one way. Other paths require multiple transactions. +PLATFORM_INTERFACE int TranslateStackInfo( const void * const *pCallStack, int iCallStackCount, tchar *szOutput, int iOutBufferSize, const tchar *szEntrySeparator, TranslateStackInfo_StyleFlags_t style = TSISTYLEFLAG_DEFAULT ); + +PLATFORM_INTERFACE void PreloadStackInformation( void * const *pAddresses, int iAddressCount ); //caches data and reduces communication with VXConsole to speed up 360 decoding when using any of the Get***FromAddress() functions. Nop on PC. +PLATFORM_INTERFACE bool GetFileAndLineFromAddress( const void *pAddress, tchar *pFileNameOut, int iMaxFileNameLength, uint32 &iLineNumberOut, uint32 *pDisplacementOut = NULL ); +PLATFORM_INTERFACE bool GetSymbolNameFromAddress( const void *pAddress, tchar *pSymbolNameOut, int iMaxSymbolNameLength, uint64 *pDisplacementOut = NULL ); +PLATFORM_INTERFACE bool GetModuleNameFromAddress( const void *pAddress, tchar *pModuleNameOut, int iMaxModuleNameLength ); + + + +class PLATFORM_CLASS CCallStackStorage //a helper class to grab a stack trace as close to the leaf code surface as possible, then pass it on to deeper functions intact with less unpredictable inlining pollution +{ +public: + CCallStackStorage( FN_GetCallStack GetStackFunction = GetCallStack, uint32 iSkipCalls = 0 ); + CCallStackStorage( const CCallStackStorage ©From ) + { + iValidEntries = copyFrom.iValidEntries; + memcpy( pStack, copyFrom.pStack, sizeof( void * ) * copyFrom.iValidEntries ); + } + + void *pStack[128]; //probably too big, possibly too small for some applications. Don't want to spend the time figuring out how to generalize this without templatizing pollution or mallocs + uint32 iValidEntries; +}; + + +//Hold onto one of these to denote the top of a functional stack trace. Also allows us to string together threads to their parents +class PLATFORM_CLASS CStackTop_Base +{ +protected: +#if defined( ENABLE_RUNTIME_STACK_TRANSLATION ) + CStackTop_Base *m_pPrevTop; + void *m_pStackBase; + void *m_pReplaceAddress; + + void * const *m_pParentStackTrace; + int m_iParentStackTraceLength; +#endif +}; + +//makes a copy of the parent stack +class PLATFORM_CLASS CStackTop_CopyParentStack : public CStackTop_Base +{ +public: + CStackTop_CopyParentStack( void * const * pParentStackTrace, int iParentStackTraceLength ); + ~CStackTop_CopyParentStack( void ); +}; + +//just references the parent stack. Assuming that you'll keep that memory around as long as you're keeping this Stack Top marker. +class PLATFORM_CLASS CStackTop_ReferenceParentStack : public CStackTop_Base +{ +public: + CStackTop_ReferenceParentStack( void * const * pParentStackTrace = NULL, int iParentStackTraceLength = 0 ); + ~CStackTop_ReferenceParentStack( void ); + void ReleaseParentStackReferences( void ); //in case you need to delete the parent stack trace before this class goes out of scope +}; + + +//Encodes data so that every byte's most significant bit is a 1. Ensuring no null terminators. +//This puts the encoded data in the 128-255 value range. Leaving all standard ascii characters for control. +//Returns string length (not including the written null terminator as is standard). +//Or if the buffer is too small. Returns negative of necessary buffer size (including room needed for null terminator) +PLATFORM_INTERFACE int EncodeBinaryToString( const void *pToEncode, int iDataLength, char *pEncodeOut, int iEncodeBufferSize ); + +//Decodes a string produced by EncodeBinaryToString(). Safe to decode in place if you don't mind trashing your string, binary byte count always less than string byte count. +//Returns: +// >= 0 is the decoded data size +// INT_MIN (most negative value possible) indicates an improperly formatted string (not our data) +// all other negative values are the negative of how much dest buffer size is necessary. +PLATFORM_INTERFACE int DecodeBinaryFromString( const char *pString, void *pDestBuffer, int iDestBufferSize, char **ppParseFinishOut = NULL ); + + + + +// 360<->VXConsole specific communication definitions +#define XBX_CALLSTACKDECODEPREFIX ":CSDECODE[" + +enum StackTranslation_BinaryHandler_Command_t +{ + ST_BHC_LOADEDLIBARY, + ST_BHC_GETTRANSLATIONINFO, +}; + +#pragma pack(push) +#pragma pack(1) +struct FullStackInfo_t +{ + const void *pAddress; + char szModuleName[24]; + char szFileName[MAX_PATH/2]; + char szSymbol[64]; + uint32 iLine; + uint32 iSymbolOffset; + +}; +#pragma pack(pop) + +#endif //#ifndef TIER0_STACKTOOLS_H diff --git a/mp/src/public/tier0/threadtools.h b/mp/src/public/tier0/threadtools.h index 7a69f0c6..e5b720e2 100644 --- a/mp/src/public/tier0/threadtools.h +++ b/mp/src/public/tier0/threadtools.h @@ -233,7 +233,7 @@ inline void const *ThreadInterlockedExchangePointerToConst( void const * volatil inline void const *ThreadInterlockedCompareExchangePointerToConst( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedCompareExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } inline bool ThreadInterlockedAssignPointerToConstIf( void const * volatile *p, void const *value, void const *comperand ) { return ThreadInterlockedAssignPointerIf( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ), const_cast < void * > ( comperand ) ); } -#if defined( X64BITS ) +#if defined( PLATFORM_64BITS ) #if defined (_WIN32) typedef __m128i int128; inline int128 int128_zero() { return _mm_setzero_si128(); } @@ -289,6 +289,30 @@ PLATFORM_INTERFACE void ThreadNotifySyncReleasing(void *p); // work in a DLL loaded with LoadLibrary() //----------------------------------------------------------------------------- +#ifndef NO_THREAD_LOCAL + +#if defined(_LINUX) && !defined(OSX) +// linux totally supports compiler thread locals, even across dll's. +#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1 +#define CTHREADLOCALINTEGER( typ ) __thread int +#define CTHREADLOCALINT __thread int +#define CTHREADLOCALPTR( typ ) __thread typ * +#define CTHREADLOCAL( typ ) __thread typ +#define GETLOCAL( x ) ( x ) +#endif // _LINUX && !OSX + +#if defined(WIN32) || defined(OSX) +#ifndef __AFXTLS_H__ // not compatible with some Windows headers +#define CTHREADLOCALINT CThreadLocalInt<int> +#define CTHREADLOCALINTEGER( typ ) CThreadLocalInt<typ> +#define CTHREADLOCALPTR( typ ) CThreadLocalPtr<typ> +#define CTHREADLOCAL( typ ) CThreadLocal<typ> +#define GETLOCAL( x ) ( x.Get() ) +#endif +#endif // WIN32 || OSX + +#endif // NO_THREAD_LOCALS + #ifndef __AFXTLS_H__ // not compatible with some Windows headers #ifndef NO_THREAD_LOCAL @@ -484,7 +508,7 @@ public: bool operator==( T *rhs ) const { return ( m_value == rhs ); } bool operator!=( T *rhs ) const { return ( m_value != rhs ); } -#ifdef X64BITS +#if defined( PLATFORM_64BITS ) T *operator++() { return ((T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) )) + 1; } T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) ); } @@ -523,6 +547,41 @@ private: T * volatile m_value; }; +//----------------------------------------------------------------------------- +// +// Platform independent verification that multiple threads aren't getting into the same code at the same time. +// Note: This is intended for use to identify problems, it doesn't provide any sort of thread safety. +// +//----------------------------------------------------------------------------- +class ReentrancyVerifier +{ +public: + inline ReentrancyVerifier(CInterlockedInt* counter, int sleepTimeMS) + : mCounter(counter) + { + Assert(mCounter != NULL); + + if (++(*mCounter) != 1) { + DebuggerBreakIfDebugging_StagingOnly(); + } + + if (sleepTimeMS > 0) + { + ThreadSleep(sleepTimeMS); + } + } + + inline ~ReentrancyVerifier() + { + if (--(*mCounter) != 0) { + DebuggerBreakIfDebugging_StagingOnly(); + } + } + +private: + CInterlockedInt* mCounter; +}; + //----------------------------------------------------------------------------- // diff --git a/mp/src/public/tier0/vprof.h b/mp/src/public/tier0/vprof.h index 9464e4ad..1c7321bb 100644 --- a/mp/src/public/tier0/vprof.h +++ b/mp/src/public/tier0/vprof.h @@ -140,6 +140,8 @@ #define VPROF_BUDGETGROUP_TENFOOT VPROF_BUDGETGROUP_HTMLSURFACE #define VPROF_BUDGETGROUP_STEAMUI VPROF_BUDGETGROUP_HTMLSURFACE #define VPROF_BUDGETGROUP_ATTRIBUTES _T("Attributes") +#define VPROF_BUDGETGROUP_FINDATTRIBUTE _T("FindAttribute") +#define VPROF_BUDGETGROUP_FINDATTRIBUTEUNSAFE _T("FindAttributeUnsafe") #ifdef _X360 // update flags diff --git a/mp/src/public/tier0/vprof_telemetry.h b/mp/src/public/tier0/vprof_telemetry.h index a7758cf4..c60bde5d 100644 --- a/mp/src/public/tier0/vprof_telemetry.h +++ b/mp/src/public/tier0/vprof_telemetry.h @@ -133,7 +133,7 @@ public: float time = ( tmFastTime() - time0 ) * g_Telemetry.flRDTSCToMilliSeconds; if( time >= m_threshold ) { - tmMessage( TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(dota/spike)%s %.2fms %t", m_message, time, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) ); + tmMessage( TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(source/spike)%s %.2fms %t", m_message, time, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) ); } } diff --git a/mp/src/public/tier0/wchartypes.h b/mp/src/public/tier0/wchartypes.h index 9803870c..814470fd 100644 --- a/mp/src/public/tier0/wchartypes.h +++ b/mp/src/public/tier0/wchartypes.h @@ -88,6 +88,14 @@ typedef char tchar; #define TCHAR_IS_CHAR #endif +#if defined( _MSC_VER ) || defined( WIN32 ) +typedef wchar_t uchar16; +typedef unsigned int uchar32; +#else +typedef unsigned short uchar16; +typedef wchar_t uchar32; +#endif + #ifdef FORCED_UNICODE #undef _UNICODE #endif |