summaryrefslogtreecommitdiff
path: root/external/vpc/public/tier0
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /external/vpc/public/tier0
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'external/vpc/public/tier0')
-rw-r--r--external/vpc/public/tier0/annotations.h116
-rw-r--r--external/vpc/public/tier0/basetypes.h650
-rw-r--r--external/vpc/public/tier0/commonmacros.h149
-rw-r--r--external/vpc/public/tier0/dbg.h716
-rw-r--r--external/vpc/public/tier0/dbgflag.h68
-rw-r--r--external/vpc/public/tier0/etwprof.h155
-rw-r--r--external/vpc/public/tier0/eventmasks.h480
-rw-r--r--external/vpc/public/tier0/eventmodes.h1787
-rw-r--r--external/vpc/public/tier0/fasttimer.h625
-rw-r--r--external/vpc/public/tier0/ia32detect.h383
-rw-r--r--external/vpc/public/tier0/icommandline.h65
-rw-r--r--external/vpc/public/tier0/ioctlcodes.h29
-rw-r--r--external/vpc/public/tier0/k8performancecounters.h2040
-rw-r--r--external/vpc/public/tier0/l2cache.h47
-rw-r--r--external/vpc/public/tier0/logging.h767
-rw-r--r--external/vpc/public/tier0/mem.h50
-rw-r--r--external/vpc/public/tier0/memalloc.h701
-rw-r--r--external/vpc/public/tier0/memdbgoff.h25
-rw-r--r--external/vpc/public/tier0/memdbgon.h281
-rw-r--r--external/vpc/public/tier0/memvirt.h46
-rw-r--r--external/vpc/public/tier0/minidump.h82
-rw-r--r--external/vpc/public/tier0/p4performancecounters.h322
-rw-r--r--external/vpc/public/tier0/p5p6performancecounters.h225
-rw-r--r--external/vpc/public/tier0/platform.h2032
-rw-r--r--external/vpc/public/tier0/pmelib.h212
-rw-r--r--external/vpc/public/tier0/stackstats.h966
-rw-r--r--external/vpc/public/tier0/stacktools.h153
-rw-r--r--external/vpc/public/tier0/threadtools.h2402
-rw-r--r--external/vpc/public/tier0/threadtools.inl629
-rw-r--r--external/vpc/public/tier0/tslist.h858
-rw-r--r--external/vpc/public/tier0/validator.h73
-rw-r--r--external/vpc/public/tier0/valobject.h72
-rw-r--r--external/vpc/public/tier0/valve_off.h33
-rw-r--r--external/vpc/public/tier0/valve_on.h37
-rw-r--r--external/vpc/public/tier0/vprof.h1510
-rw-r--r--external/vpc/public/tier0/vprof_sn.h31
-rw-r--r--external/vpc/public/tier0/wchartypes.h101
-rw-r--r--external/vpc/public/tier0/win32consoleio.h32
-rw-r--r--external/vpc/public/tier0/xbox_codeline_defines.h16
39 files changed, 18966 insertions, 0 deletions
diff --git a/external/vpc/public/tier0/annotations.h b/external/vpc/public/tier0/annotations.h
new file mode 100644
index 0000000..d10e530
--- /dev/null
+++ b/external/vpc/public/tier0/annotations.h
@@ -0,0 +1,116 @@
+#ifndef ANALYSIS_ANNOTATIONS_H
+#define ANALYSIS_ANNOTATIONS_H
+
+#if _MSC_VER >= 1600 // VS 2010 and above.
+//-----------------------------------------------------------------------------
+// Upgrading important helpful warnings to errors
+//-----------------------------------------------------------------------------
+#pragma warning(error : 4789 ) // warning C4789: destination of memory copy is too small
+
+// Suppress some code analysis warnings
+#ifdef _PREFAST_
+// Include the annotation header file.
+#include <sal.h>
+
+// /Analyze warnings can only be suppressed when using a compiler that supports them, which VS 2010
+// Professional does not.
+
+// We don't care about these warnings because they are bugs that can only occur during resource
+// exhaustion or other unexpected API failure, which we are nowhere near being able to handle.
+#pragma warning(disable : 6308) // warning C6308: 'realloc' might return null pointer: assigning null pointer to 's_ppTestCases', which is passed as an argument to 'realloc', will cause the original memory block to be leaked
+#pragma warning(disable : 6255) // warning C6255: _alloca indicates failure by raising a stack overflow exception. Consider using _malloca instead
+#pragma warning(disable : 6387) // warning C6387: 'argument 1' might be '0': this does not adhere to the specification for the function 'GetProcAddress'
+#pragma warning(disable : 6309) // warning C6309: Argument '1' is null: this does not adhere to function specification of 'GetProcAddress'
+#pragma warning(disable : 6011) // warning C6011: Dereferencing NULL pointer 'm_ppTestCases'
+#pragma warning(disable : 6211) // warning C6211: Leaking memory 'newKeyValue' due to an exception. Consider using a local catch block to clean up memory
+#pragma warning(disable : 6031) // warning C6031: Return value ignored: '_getcwd'
+
+// These warnings are because /analyze doesn't like our use of constants, especially things like IsPC()
+#pragma warning(disable : 6326) // warning C6326: Potential comparison of a constant with another constant
+#pragma warning(disable : 6239) // warning C6239: (<non-zero constant> && <expression>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?
+#pragma warning(disable : 6285) // warning C6285: (<non-zero constant> || <non-zero constant>) is always a non-zero constant. Did you intend to use the bitwise-and operator?
+#pragma warning(disable : 6237) // warning C6237: (<zero> && <expression>) is always zero. <expression> is never evaluated and might have side effects
+#pragma warning(disable : 6235) // warning C6235: (<non-zero constant> || <expression>) is always a non-zero constant
+#pragma warning(disable : 6240) // warning C6240: (<expression> && <non-zero constant>) always evaluates to the result of <expression>. Did you intend to use the bitwise-and operator?
+
+// These warnings aren't really important:
+#pragma warning(disable : 6323) // warning C6323: Use of arithmetic operator on Boolean type(s)
+
+// Miscellaneous other /analyze warnings. We should consider fixing these at some point.
+//#pragma warning(disable : 6204) // warning C6204: Possible buffer overrun in call to 'memcpy': use of unchecked parameter 'src'
+//#pragma warning(disable : 6262) // warning C6262: Function uses '16464' bytes of stack: exceeds /analyze:stacksize'16384'. Consider moving some data to heap
+// This is a serious warning. Don't suppress it.
+//#pragma warning(disable : 6263) // warning C6263: Using _alloca in a loop: this can quickly overflow stack
+// 6328 is also used for passing __int64 to printf when int is expected so we can't suppress it.
+//#pragma warning(disable : 6328) // warning C6328: 'char' passed as parameter '1' when 'unsigned char' is required in call to 'V_isdigit'
+// /analyze doesn't like GCOMPILER_ASSERT's implementation of compile-time asserts
+#pragma warning(disable : 6326) // warning C6326: Potential comparison of a constant with another constant
+#pragma warning(disable : 6335) // warning C6335: Leaking process information handle 'pi.hThread'
+#pragma warning(disable : 6320) // warning C6320: Exception-filter expression is the constant EXCEPTION_EXECUTE_HANDLER. This might mask exceptions that were not intended to be handled
+#pragma warning(disable : 6250) // warning C6250: Calling 'VirtualFree' without the MEM_RELEASE flag might free memory but not address descriptors (VADs). This causes address space leaks
+#pragma warning(disable : 6384) // ientity2_class_h_schema_gen.cpp(76): warning C6384: Dividing sizeof a pointer by another value
+
+// For temporarily suppressing warnings -- the warnings are suppressed for the next source line.
+#define ANALYZE_SUPPRESS(wnum) __pragma(warning(suppress: wnum))
+#define ANALYZE_SUPPRESS2(wnum1, wnum2) __pragma(warning(supress: wnum1 wnum2))
+#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3) __pragma(warning(suppress: wnum1 wnum2 wnum3))
+#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4) __pragma(warning(suppress: wnum1 wnum2 wnum3 wnum4))
+
+// Tag all printf style format strings with this
+#define PRINTF_FORMAT_STRING _Printf_format_string_
+#define SCANF_FORMAT_STRING _Scanf_format_string_impl_
+// Various macros for specifying the capacity of the buffer pointed
+// to by a function parameter. Variations include in/out/inout,
+// CAP (elements) versus BYTECAP (bytes), and null termination or
+// not (_Z).
+#define IN_Z _In_z_
+#define IN_CAP(x) _In_count_(x)
+#define IN_BYTECAP(x) _In_bytecount_(x)
+#define OUT_Z_CAP(x) _Out_z_cap_(x)
+#define OUT_CAP(x) _Out_cap_(x)
+#define OUT_BYTECAP(x) _Out_bytecap_(x)
+#define OUT_Z_BYTECAP(x) _Out_z_bytecap_(x)
+#define INOUT_BYTECAP(x) _Inout_bytecap_(x)
+#define INOUT_Z_CAP(x) _Inout_z_cap_(x)
+#define INOUT_Z_BYTECAP(x) _Inout_z_bytecap_(x)
+// These macros are use for annotating array reference parameters, typically used in functions
+// such as V_strcpy_safe. Because they are array references the capacity is already known.
+#if _MSC_VER >= 1700
+#define IN_Z_ARRAY _Pre_z_
+#define OUT_Z_ARRAY _Post_z_
+#define INOUT_Z_ARRAY _Prepost_z_
+#else
+#define IN_Z_ARRAY _Deref_pre_z_
+#define OUT_Z_ARRAY _Deref_post_z_
+#define INOUT_Z_ARRAY _Deref_prepost_z_
+#endif // _MSC_VER >= 1700
+// Use the macros above to annotate string functions that fill buffers as shown here,
+// in order to give VS's /analyze more opportunities to find bugs.
+// void V_wcsncpy( OUT_Z_BYTECAP(maxLenInBytes) wchar_t *pDest, wchar_t const *pSrc, int maxLenInBytes );
+// int V_snwprintf( OUT_Z_CAP(maxLenInCharacters) wchar_t *pDest, int maxLenInCharacters, PRINTF_FORMAT_STRING const wchar_t *pFormat, ... );
+
+#endif // _PREFAST_
+#endif // _MSC_VER >= 1600 // VS 2010 and above.
+
+#ifndef ANALYZE_SUPPRESS
+#define ANALYZE_SUPPRESS(wnum)
+#define ANALYZE_SUPPRESS2(wnum1, wnum2)
+#define ANALYZE_SUPPRESS3(wnum1, wnum2, wnum3)
+#define ANALYZE_SUPPRESS4(wnum1, wnum2, wnum3, wnum4)
+#define PRINTF_FORMAT_STRING
+#define SCANF_FORMAT_STRING
+#define IN_Z
+#define IN_CAP(x)
+#define IN_BYTECAP(x)
+#define OUT_Z_CAP(x)
+#define OUT_CAP(x)
+#define OUT_BYTECAP(x)
+#define OUT_Z_BYTECAP(x)
+#define INOUT_BYTECAP(x)
+#define INOUT_Z_CAP(x)
+#define INOUT_Z_BYTECAP(x)
+#define OUT_Z_ARRAY
+#define INOUT_Z_ARRAY
+#endif
+
+#endif // ANALYSIS_ANNOTATIONS_H
diff --git a/external/vpc/public/tier0/basetypes.h b/external/vpc/public/tier0/basetypes.h
new file mode 100644
index 0000000..caa297e
--- /dev/null
+++ b/external/vpc/public/tier0/basetypes.h
@@ -0,0 +1,650 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef BASETYPES_H
+#define BASETYPES_H
+
+#ifdef COMPILER_MSVC
+#pragma once
+#endif
+
+// This is a trick to get the DLL extension off the -D option on the command line.
+#define DLLExtTokenPaste(x) #x
+#define DLLExtTokenPaste2(x) DLLExtTokenPaste(x)
+#define DLL_EXT_STRING DLLExtTokenPaste2( _DLL_EXT )
+
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef schema
+#define schema namespace ValveSchemaMarker {}
+#endif
+
+#ifdef COMPILING_SCHEMA
+#define UNSCHEMATIZED_METHOD( x )
+#else
+#define UNSCHEMATIZED_METHOD( x ) x
+#endif
+
+//////////////////////////////////////////////////////////////////////////
+
+#include "tier0/platform.h"
+#include "commonmacros.h"
+#include "wchartypes.h"
+#ifdef _PS3
+#include <float.h>
+#elif defined( PLATFORM_POSIX )
+#include <math.h>
+#endif
+
+#include "tier0/valve_off.h"
+
+// There's a different version of this file in the xbox codeline
+// so the PC version built in the xbox branch includes things like
+// tickrate changes.
+#include "xbox_codeline_defines.h"
+
+#if defined(_PS3)
+#include <ppu_intrinsics.h>
+#include <sys/fs.h>
+#define PATH_MAX CELL_FS_MAX_FS_PATH_LENGTH
+#define _MAX_PATH PATH_MAX
+#endif
+// stdio.h
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifdef PLATFORM_POSIX
+#include <stdint.h>
+
+template<class T>
+T abs( const T &a )
+{
+ if ( a < 0 )
+ return -a;
+ else
+ return a;
+}
+#endif
+
+#define ExecuteNTimes( nTimes, x ) \
+ { \
+ static int __executeCount=0;\
+ if ( __executeCount < nTimes )\
+ { \
+ ++__executeCount; \
+ x; \
+ } \
+ }
+
+
+#define ExecuteOnce( x ) ExecuteNTimes( 1, x )
+
+
+
+// Pad a number so it lies on an N byte boundary.
+// So PAD_NUMBER(0,4) is 0 and PAD_NUMBER(1,4) is 4
+#define PAD_NUMBER(number, boundary) \
+ ( ((number) + ((boundary)-1)) / (boundary) ) * (boundary)
+
+// In case this ever changes
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+
+// #define COMPILETIME_MAX and COMPILETIME_MIN for max/min in constant expressions
+#define COMPILETIME_MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+#define COMPILETIME_MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#ifndef MIN
+#define MIN( a, b ) ( ( ( a ) < ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+#ifndef MAX
+#define MAX( a, b ) ( ( ( a ) > ( b ) ) ? ( a ) : ( b ) )
+#endif
+
+
+
+
+#ifdef __cplusplus
+
+template< class T, class Y, class X >
+inline T clamp( T const &val, Y const &minVal, X const &maxVal )
+{
+ if( val < minVal )
+ return minVal;
+ else if( val > maxVal )
+ return maxVal;
+ else
+ return val;
+}
+
+#else
+
+#define clamp(val, min, max) (((val) > (max)) ? (max) : (((val) < (min)) ? (min) : (val)))
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+//-----------------------------------------------------------------------------
+// fsel
+//-----------------------------------------------------------------------------
+#if !defined(_PS3) && !defined(_X360)
+
+#define fsel(c,x,y) ( (c) >= 0 ? (x) : (y) )
+
+// integer conditional move
+// if a >= 0, return x, else y
+#define isel(a,x,y) ( ((a) >= 0) ? (x) : (y) )
+
+// if x = y, return a, else b
+#define ieqsel(x,y,a,b) (( (x) == (y) ) ? (a) : (b))
+
+// if the nth bit of a is set (counting with 0 = LSB),
+// return x, else y
+// this is fast if nbit is a compile-time immediate
+#define ibitsel(a, nbit, x, y) ( ( ((a) & (1 << (nbit))) != 0 ) ? (x) : (y) )
+
+
+FORCEINLINE double fpmin( double a, double b )
+{
+ return a > b ? b : a;
+}
+
+FORCEINLINE double fpmax( double a, double b )
+{
+ return a >= b ? a : b;
+}
+
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE float fclamp( float x, float a, float b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE double fclamp( double x, double a, double b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+
+// At some point, we will need a unified API.
+#define imin( x, y ) ( (x) < (y) ? (x) : (y) )
+#define imax( x, y ) ( (x) > (y) ? (x) : (y) )
+#define iclamp clamp
+
+#else
+
+// __fsel(double fComparand, double fValGE, double fLT) == fComparand >= 0 ? fValGE : fLT
+// this is much faster than if ( aFloat > 0 ) { x = .. }
+// the XDK defines two intrinsics, one for floats and one for doubles -- it's the same
+// opcode, but the __fself version tells the compiler not to do a wasteful unnecessary
+// rounding op after each sel.
+// #define fsel __fsel
+#ifdef _X360
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) { return __fsel( fComparand, fValGE, fLT ); }
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) { return __fself( fComparand, fValGE, fLT ); }
+#else
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT) { return __fsel( fComparand, fValGE, fLT ); }
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT) { return __fsels( fComparand, fValGE, fLT ); }
+#endif
+
+#if !defined(_X360)
+FORCEINLINE float fpmin( float a, float b )
+{
+ return fsel( a-b, b,a);
+}
+FORCEINLINE double fpmin( double a, double b )
+{
+ return fsel( a-b, b,a);
+}
+
+FORCEINLINE float fpmax( float a, float b )
+{
+ return fsel( a-b, a,b);
+}
+FORCEINLINE double fpmax( double a, double b )
+{
+ return fsel( a-b, a,b);
+}
+
+// any mixed calls should promote to double
+FORCEINLINE double fpmax(float a, double b)
+{
+ return fpmax( (double) a, b );
+}
+// any mixed calls should promote to double
+FORCEINLINE double fpmax(double a, float b)
+{
+ return fpmax( (double) a, (double) b );
+}
+#endif
+
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE float fclamp( float x, float a, float b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+// clamp x to lie inside [a,b]. Assumes b>a
+FORCEINLINE double fclamp( double x, double a, double b )
+{
+ return fpmin( fpmax( x, a ), b );
+}
+
+// if a >= 0, return x, else y
+FORCEINLINE int isel( int a, int x, int y )
+{
+ int mask = a >> 31; // arithmetic shift right, splat out the sign bit
+ return x + ((y - x) & mask);
+};
+
+// if a >= 0, return x, else y
+FORCEINLINE unsigned isel( int a, unsigned x, unsigned y )
+{
+ int mask = a >> 31; // arithmetic shift right, splat out the sign bit
+ return x + ((y - x) & mask);
+};
+
+// ( x == y ) ? a : b
+FORCEINLINE unsigned ieqsel( unsigned x, unsigned y, unsigned a, unsigned b )
+{
+ unsigned mask = (x == y) ? 0 : -1;
+ return a + ((b - a) & mask);
+};
+
+// ( x == y ) ? a : b
+FORCEINLINE int ieqsel( int x, int y, int a, int b )
+{
+ int mask = (x == y) ? 0 : -1;
+ return a + ((b - a) & mask);
+};
+
+FORCEINLINE int imin( int x, int y )
+{
+ int nMaxSign = x - y; // Positive if x greater than y
+ int nMaxMask = nMaxSign >> 31; // 0 if x greater than y, 0xffffffff if x smaller than y
+ int nMaxSaturated = y + ( nMaxSign & nMaxMask );
+ return nMaxSaturated;
+}
+
+FORCEINLINE int imax( int x, int y )
+{
+ int nMinSign = y - x; // Positive if x smaller than y
+ int nMinMask = nMinSign >> 31; // 0 if x smaller than y, 0xffffffff if x greater than y
+ int nMinSaturated = y - ( nMinSign & nMinMask);
+ return nMinSaturated;
+}
+
+FORCEINLINE int iclamp( int x, int min, int max )
+{
+ int nResult = imin( x, max );
+ return imax( nResult, min );
+}
+
+// if the nth bit of a is set (counting with 0 = LSB),
+// return x, else y
+// this is fast if nbit is a compile-time immediate
+#define ibitsel(a, nbit, x, y) ( (x) + (((y) - (x)) & (((a) & (1 << (nbit))) ? 0 : -1)) )
+
+#endif
+
+#if CROSS_PLATFORM_VERSION < 1
+
+#ifndef DONT_DEFINE_BOOL // Needed for Cocoa stuff to compile.
+typedef int BOOL;
+#endif
+
+typedef int qboolean;
+//typedef uint32 ULONG;
+typedef uint8 BYTE;
+typedef uint8 byte;
+typedef uint16 word;
+#endif
+
+#if defined( _WIN32 ) || defined( _PS3 )
+typedef wchar_t ucs2; // under windows & PS3 wchar_t is ucs2
+#else
+typedef unsigned short ucs2;
+#endif
+
+enum ThreeState_t
+{
+ TRS_FALSE,
+ TRS_TRUE,
+ TRS_NONE,
+};
+
+typedef float vec_t;
+#ifdef _WIN32
+typedef __int32 vec_t_as_gpr; // a general purpose register type equal in size to a vec_t (in case we have to avoid the fpu for some reason)
+#endif
+
+
+template <typename T>
+inline T AlignValue( T val, uintp alignment )
+{
+ return (T)( ( (uintp)val + alignment - 1 ) & ~( alignment - 1 ) );
+}
+
+
+// FIXME: this should move
+#ifndef __cplusplus
+#define true TRUE
+#define false FALSE
+#endif
+
+//-----------------------------------------------------------------------------
+// look for NANs, infinities, and underflows.
+// This assumes the ANSI/IEEE 754-1985 standard
+//-----------------------------------------------------------------------------
+
+#ifdef __cplusplus
+
+inline uint32 FloatBits( const vec_t &f )
+{
+ union Convertor_t
+ {
+ vec_t f;
+ uint32 ul;
+ }tmp;
+
+ switch( false ) { case false: ; case (sizeof( tmp ) == 4 && sizeof( tmp.f ) == 4 && sizeof( tmp.ul ) == 4):; };
+ tmp.f = f;
+ return tmp.ul;
+}
+
+inline vec_t BitsToFloat( uint32 i )
+{
+ union Convertor_t
+ {
+ vec_t f;
+ uint32 ul;
+ }tmp;
+ switch( false ) { case false: ; case (sizeof( tmp ) == 4 && sizeof( tmp.f ) == 4 && sizeof( tmp.ul ) == 4 ):; };
+ tmp.ul = i;
+ return tmp.f;
+}
+
+inline bool IsFinite( const vec_t &f )
+{
+#ifdef _GAMECONSOLE
+ return f == f && fabs(f) <= FLT_MAX;
+#else
+ return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
+#endif
+}
+
+#if defined( WIN32 )
+
+//#include <math.h>
+// Just use prototype from math.h
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ double __cdecl fabs(double);
+ //_CRT_JIT_INTRINSIC _CRTIMP float __cdecl fabsf( __in float _X);
+ float __cdecl fabsf( _In_ float );
+#ifdef __cplusplus
+}
+#endif
+
+// In win32 try to use the intrinsic fabs so the optimizer can do it's thing inline in the code
+#pragma intrinsic( fabs )
+// Also, alias float make positive to use fabs, too
+// NOTE: Is there a perf issue with double<->float conversion?
+inline float FloatMakePositive( vec_t f )
+{
+ return fabsf( f );
+}
+#else
+inline float FloatMakePositive( vec_t f )
+{
+ return fabsf(f); // was since 2002: BitsToFloat( FloatBits(f) & 0x7FFFFFFF ); fixed in 2010
+}
+#endif
+
+inline float FloatNegate( vec_t f )
+{
+ return -f; //BitsToFloat( FloatBits(f) ^ 0x80000000 );
+}
+
+
+#define FLOAT32_NAN_BITS (uint32)0x7FC00000 // not a number!
+#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS )
+
+#define VEC_T_NAN FLOAT32_NAN
+
+#endif
+
+inline float FloatMakeNegative( vec_t f )
+{
+ return -fabsf( f );// was since 2002: BitsToFloat( FloatBits(f) | 0x80000000 ); fixed in 2010
+}
+
+
+// FIXME: why are these here? Hardly anyone actually needs them.
+struct color24
+{
+ byte r, g, b;
+};
+
+typedef struct color32_s
+{
+ bool operator!=( const struct color32_s &other ) const;
+ byte r, g, b, a;
+
+ // assign and copy by using the whole register rather
+ // than byte-by-byte copy. (No, the compiler is not
+ // smart enough to do this for you. /FAcs if you
+ // don't believe me.)
+ inline unsigned *asInt(void) { return reinterpret_cast<unsigned*>(this); }
+ inline const unsigned *asInt(void) const { return reinterpret_cast<const unsigned*>(this); }
+ // This thing is in a union elsewhere, and union members can't have assignment
+ // operators, so you have to explicitly assign using this, or be slow. SUCK.
+ inline void Copy(const color32_s &rhs)
+ {
+ *asInt() = *rhs.asInt();
+ }
+
+} color32;
+
+inline bool color32::operator!=( const color32 &other ) const
+{
+ return r != other.r || g != other.g || b != other.b || a != other.a;
+}
+
+struct colorVec
+{
+ unsigned r, g, b, a;
+};
+
+
+#ifndef NOTE_UNUSED
+#define NOTE_UNUSED(arg) ((void)arg) // for pesky compiler / lint warnings
+#endif
+#ifdef __cplusplus
+
+struct vrect_t
+{
+ int x,y,width,height;
+ vrect_t *pnext;
+};
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// MaterialRect_t struct - used for DrawDebugText
+//-----------------------------------------------------------------------------
+struct Rect_t
+{
+ int x, y;
+ int width, height;
+};
+
+struct Rect3D_t
+{
+ int x, y, z;
+ int width, height, depth;
+
+ FORCEINLINE Rect3D_t( int nX, int nY, int nZ, int nWidth, int nHeight, int nDepth )
+ {
+ x = nX;
+ y = nY;
+ z = nZ;
+ width = nWidth;
+ height = nHeight;
+ depth = nDepth;
+ }
+
+ FORCEINLINE Rect3D_t( void )
+ {
+ }
+
+};
+
+
+
+//-----------------------------------------------------------------------------
+// Interval, used by soundemittersystem + the game
+//-----------------------------------------------------------------------------
+struct interval_t
+{
+ float start;
+ float range;
+};
+
+
+//-----------------------------------------------------------------------------
+// Declares a type-safe handle type; you can't assign one handle to the next
+//-----------------------------------------------------------------------------
+
+// 32-bit pointer handles.
+
+// Typesafe 8-bit and 16-bit handles.
+template< class HandleType >
+class CBaseIntHandle
+{
+public:
+
+ inline bool operator==( const CBaseIntHandle &other ) { return m_Handle == other.m_Handle; }
+ inline bool operator!=( const CBaseIntHandle &other ) { return m_Handle != other.m_Handle; }
+
+ // Only the code that doles out these handles should use these functions.
+ // Everyone else should treat them as a transparent type.
+ inline HandleType GetHandleValue() { return m_Handle; }
+ inline void SetHandleValue( HandleType val ) { m_Handle = val; }
+
+ typedef HandleType HANDLE_TYPE;
+
+protected:
+
+ HandleType m_Handle;
+};
+
+template< class DummyType >
+class CIntHandle16 : public CBaseIntHandle< unsigned short >
+{
+public:
+ inline CIntHandle16() {}
+
+ static inline CIntHandle16<DummyType> MakeHandle( HANDLE_TYPE val )
+ {
+ return CIntHandle16<DummyType>( val );
+ }
+
+protected:
+ inline CIntHandle16( HANDLE_TYPE val )
+ {
+ m_Handle = val;
+ }
+};
+
+
+template< class DummyType >
+class CIntHandle32 : public CBaseIntHandle< uint32 >
+{
+public:
+ inline CIntHandle32() {}
+
+ static inline CIntHandle32<DummyType> MakeHandle( HANDLE_TYPE val )
+ {
+ return CIntHandle32<DummyType>( val );
+ }
+
+protected:
+ inline CIntHandle32( HANDLE_TYPE val )
+ {
+ m_Handle = val;
+ }
+};
+
+
+// NOTE: This macro is the same as windows uses; so don't change the guts of it
+#define DECLARE_HANDLE_16BIT(name) typedef CIntHandle16< struct name##__handle * > name;
+#define DECLARE_HANDLE_32BIT(name) typedef CIntHandle32< struct name##__handle * > name;
+
+#define DECLARE_POINTER_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name
+#define FORWARD_DECLARE_HANDLE(name) typedef struct name##__ *name
+
+#define DECLARE_DERIVED_POINTER_HANDLE( _name, _basehandle ) struct _name##__ : public _basehandle##__ {}; typedef struct _name##__ *_name
+#define DECLARE_ALIASED_POINTER_HANDLE( _name, _alias ) typedef struct _alias##__ *name
+
+// @TODO: Find a better home for this
+#if !defined(_STATIC_LINKED) && !defined(PUBLISH_DLL_SUBSYSTEM)
+// for platforms built with dynamic linking, the dll interface does not need spoofing
+#define PUBLISH_DLL_SUBSYSTEM()
+#endif
+
+#define UID_PREFIX generated_id_
+#define UID_CAT1(a,c) a ## c
+#define UID_CAT2(a,c) UID_CAT1(a,c)
+#define EXPAND_CONCAT(a,c) UID_CAT1(a,c)
+#ifdef _MSC_VER
+#define UNIQUE_ID UID_CAT2(UID_PREFIX,__COUNTER__)
+#else
+#define UNIQUE_ID UID_CAT2(UID_PREFIX,__LINE__)
+#endif
+
+#define _MKSTRING(arg) #arg
+#define MKSTRING(arg) _MKSTRING(arg)
+
+
+// this allows enumerations to be used as flags, and still remain type-safe!
+#define DEFINE_ENUM_BITWISE_OPERATORS( Type ) \
+ inline Type operator| ( Type a, Type b ) { return Type( int( a ) | int( b ) ); } \
+ inline Type operator& ( Type a, Type b ) { return Type( int( a ) & int( b ) ); } \
+ inline Type operator^ ( Type a, Type b ) { return Type( int( a ) ^ int( b ) ); } \
+ inline Type operator<< ( Type a, int b ) { return Type( int( a ) << b ); } \
+ inline Type operator>> ( Type a, int b ) { return Type( int( a ) >> b ); } \
+ inline Type &operator|= ( Type &a, Type b ) { return a = a | b; } \
+ inline Type &operator&= ( Type &a, Type b ) { return a = a & b; } \
+ inline Type &operator^= ( Type &a, Type b ) { return a = a ^ b; } \
+ inline Type &operator<<=( Type &a, int b ) { return a = a << b; } \
+ inline Type &operator>>=( Type &a, int b ) { return a = a >> b; } \
+ inline Type operator~( Type a ) { return Type( ~int( a ) ); }
+
+// defines increment/decrement operators for enums for easy iteration
+#define DEFINE_ENUM_INCREMENT_OPERATORS( Type ) \
+ inline Type &operator++( Type &a ) { return a = Type( int( a ) + 1 ); } \
+ inline Type &operator--( Type &a ) { return a = Type( int( a ) - 1 ); } \
+ inline Type operator++( Type &a, int ) { Type t = a; ++a; return t; } \
+ inline Type operator--( Type &a, int ) { Type t = a; --a; return t; }
+
+// Max 2 player splitscreen in portal (don't merge this back), saves a bunch of memory [8/31/2010 tom]
+#define MAX_SPLITSCREEN_CLIENT_BITS 1
+// this should == MAX_JOYSTICKS in InputEnums.h
+#define MAX_SPLITSCREEN_CLIENTS ( 1 << MAX_SPLITSCREEN_CLIENT_BITS ) // 2
+
+#include "tier0/valve_on.h"
+
+#endif // BASETYPES_H
diff --git a/external/vpc/public/tier0/commonmacros.h b/external/vpc/public/tier0/commonmacros.h
new file mode 100644
index 0000000..1c12442
--- /dev/null
+++ b/external/vpc/public/tier0/commonmacros.h
@@ -0,0 +1,149 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef COMMONMACROS_H
+#define COMMONMACROS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// -------------------------------------------------------
+//
+// commonmacros.h
+//
+// This should contain ONLY general purpose macros that are
+// appropriate for use in engine/launcher/all tools
+//
+// -------------------------------------------------------
+
+// Makes a 4-byte "packed ID" int out of 4 characters
+#define MAKEID(d,c,b,a) ( ((int)(a) << 24) | ((int)(b) << 16) | ((int)(c) << 8) | ((int)(d)) )
+
+// Compares a string with a 4-byte packed ID constant
+#define STRING_MATCHES_ID( p, id ) ( (*((int *)(p)) == (id) ) ? true : false )
+#define ID_TO_STRING( id, p ) ( (p)[3] = (((id)>>24) & 0xFF), (p)[2] = (((id)>>16) & 0xFF), (p)[1] = (((id)>>8) & 0xFF), (p)[0] = (((id)>>0) & 0xFF) )
+
+#define V_ARRAYSIZE(p) (sizeof(p)/sizeof(p[0]))
+
+#define SETBITS(iBitVector, bits) ((iBitVector) |= (bits))
+#define CLEARBITS(iBitVector, bits) ((iBitVector) &= ~(bits))
+#define FBitSet(iBitVector, bits) ((iBitVector) & (bits))
+
+inline bool IsPowerOfTwo( int value )
+{
+ return (value & ( value - 1 )) == 0;
+}
+
+#ifndef REFERENCE
+#define REFERENCE(arg) ((void)arg)
+#endif
+
+#define CONST_INTEGER_AS_STRING(x) #x //Wraps the integer in quotes, allowing us to form constant strings with it
+#define __HACK_LINE_AS_STRING__(x) CONST_INTEGER_AS_STRING(x) //__LINE__ can only be converted to an actual number by going through this, otherwise the output is literally "__LINE__"
+#define __LINE__AS_STRING __HACK_LINE_AS_STRING__(__LINE__) //Gives you the line number in constant string form
+
+// Using ARRAYSIZE implementation from winnt.h:
+#ifdef ARRAYSIZE
+#undef ARRAYSIZE
+#endif
+
+// Return the number of elements in a statically sized array.
+// DWORD Buffer[100];
+// RTL_NUMBER_OF(Buffer) == 100
+// This is also popularly known as: NUMBER_OF, ARRSIZE, _countof, NELEM, etc.
+//
+#define RTL_NUMBER_OF_V1(A) (sizeof(A)/sizeof((A)[0]))
+
+#if defined(__cplusplus) && \
+ !defined(MIDL_PASS) && \
+ !defined(RC_INVOKED) && \
+ !defined(_PREFAST_) && \
+ (_MSC_FULL_VER >= 13009466) && \
+ !defined(SORTPP_PASS)
+
+// From crtdefs.h
+#if !defined(UNALIGNED)
+#if defined(_M_IA64) || defined(_M_AMD64)
+#define UNALIGNED __unaligned
+#else
+#define UNALIGNED
+#endif
+#endif
+
+// RtlpNumberOf is a function that takes a reference to an array of N Ts.
+//
+// typedef T array_of_T[N];
+// typedef array_of_T &reference_to_array_of_T;
+//
+// RtlpNumberOf returns a pointer to an array of N chars.
+// We could return a reference instead of a pointer but older compilers do not accept that.
+//
+// typedef char array_of_char[N];
+// typedef array_of_char *pointer_to_array_of_char;
+//
+// sizeof(array_of_char) == N
+// sizeof(*pointer_to_array_of_char) == N
+//
+// pointer_to_array_of_char RtlpNumberOf(reference_to_array_of_T);
+//
+// We never even call RtlpNumberOf, we just take the size of dereferencing its return type.
+// We do not even implement RtlpNumberOf, we just decare it.
+//
+// Attempts to pass pointers instead of arrays to this macro result in compile time errors.
+// That is the point.
+extern "C++" // templates cannot be declared to have 'C' linkage
+template <typename T, size_t N>
+char (*RtlpNumberOf( UNALIGNED T (&)[N] ))[N];
+
+#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
+
+// This does not work with:
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// RTL_NUMBER_OF_V2(y); // illegal use of anonymous local type in template instantiation
+// }
+//
+// You must instead do:
+//
+// struct Foo1 { int x; };
+//
+// void Foo()
+// {
+// Foo1 y[2];
+// RTL_NUMBER_OF_V2(y); // ok
+// }
+//
+// OR
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// RTL_NUMBER_OF_V1(y); // ok
+// }
+//
+// OR
+//
+// void Foo()
+// {
+// struct { int x; } y[2];
+// _ARRAYSIZE(y); // ok
+// }
+
+#else
+#define RTL_NUMBER_OF_V2(A) RTL_NUMBER_OF_V1(A)
+#endif
+
+// ARRAYSIZE is more readable version of RTL_NUMBER_OF_V2
+// _ARRAYSIZE is a version useful for anonymous types
+#define ARRAYSIZE(A) RTL_NUMBER_OF_V2(A)
+#define _ARRAYSIZE(A) RTL_NUMBER_OF_V1(A)
+
+#endif // COMMONMACROS_H
+
diff --git a/external/vpc/public/tier0/dbg.h b/external/vpc/public/tier0/dbg.h
new file mode 100644
index 0000000..2e54a47
--- /dev/null
+++ b/external/vpc/public/tier0/dbg.h
@@ -0,0 +1,716 @@
+//===== Copyright (c) Valve Corporation, All rights reserved. ========//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//====================================================================//
+#ifndef DBG_H
+#define DBG_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier0/basetypes.h"
+#include "dbgflag.h"
+#include "logging.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+
+class Color;
+
+
+//-----------------------------------------------------------------------------
+// Usage model for the Dbg library
+//
+// 1. Assertions.
+//
+// Assertions are used to detect and warn about invalid states
+//
+// To use an assertion, use
+//
+// Assert( (f == 5) );
+// AssertMsg( (f == 5), ("F needs to be %d here!\n", 5) );
+// AssertFunc( (f == 5), BadFunc() );
+// AssertEquals( f, 5 );
+// AssertFloatEquals( f, 5.0f, 1e-3 );
+//
+// The first will simply report that an assertion failed on a particular
+// code file and line. The second version will display a print-f formatted message
+// along with the file and line, the third will display a generic message and
+// will also cause the function BadFunc to be executed, and the last two
+// will report an error if f is not equal to 5 (the last one asserts within
+// a particular tolerance).
+//
+// 2. Code activation
+//
+// To cause code to be run only in debug builds, use DBG_CODE:
+// An example is below.
+//
+// DBG_CODE(
+// {
+// int x = 5;
+// ++x;
+// }
+// );
+//
+// Code can be activated based on the dynamic spew groups also. Use
+//
+// DBG_DCODE( "group", level,
+// { int x = 5; ++x; }
+// );
+//
+// 3. Breaking into the debugger.
+//
+// To cause an unconditional break into the debugger in debug builds only, use DBG_BREAK
+//
+// DBG_BREAK();
+//
+// You can force a break in any build (release or debug) using
+//
+// DebuggerBreak();
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line );
+
+#if defined( DBGFLAG_STRINGS_STRIP )
+#define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( "", 0 )
+#else
+#define DbgFlagMacro_ExitOnFatalAssert( pFile, line ) _ExitOnFatalAssert( pFile, line )
+#endif
+
+PLATFORM_INTERFACE bool ShouldUseNewAssertDialog();
+
+PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
+
+// Returns true if they want to break in the debugger.
+PLATFORM_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression );
+
+#if defined( DBGFLAG_STRINGS_STRIP )
+#define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( "", 0, "" )
+#else
+#define DbgFlagMacro_DoNewAssertDialog( pFile, line, pExpression ) DoNewAssertDialog( pFile, line, pExpression )
+#endif
+
+/* Used to define macros, never use these directly. */
+
+#ifdef _PREFAST_
+ // When doing /analyze builds define the assert macros to be __analysis_assume. This tells
+ // the compiler to assume that the condition is true, which helps to suppress many
+ // warnings. This define is done in debug and release builds, but debug builds should be
+ // preferred for static analysis because some asserts are compiled out in release.
+ // The unfortunate !! is necessary because otherwise /analyze is incapable of evaluating
+ // all of the logical expressions that the regular compiler can handle.
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) __analysis_assume( !!(_exp) )
+ #define _AssertMsgOnce( _exp, _msg, _bFatal ) __analysis_assume( !!(_exp) )
+ // Force asserts on for /analyze so that we get a __analysis_assume of all of the constraints.
+ #define DBGFLAG_ASSERT
+ #define DBGFLAG_ASSERTFATAL
+#else
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
+ do { \
+ if (!(_exp)) \
+ { \
+ LoggingResponse_t ret = Log_Assert( "%s (%d) : %s\n", __TFILE__, __LINE__, _msg ); \
+ _executeExp; \
+ if ( ret == LR_DEBUGGER ) \
+ { \
+ if ( !ShouldUseNewAssertDialog() || DbgFlagMacro_DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
+ DebuggerBreak(); \
+ if ( _bFatal ) \
+ DbgFlagMacro_ExitOnFatalAssert( __TFILE__, __LINE__ ); \
+ } \
+ } \
+ } while (0)
+
+ #define _AssertMsgOnce( _exp, _msg, _bFatal ) \
+ do { \
+ static bool fAsserted; \
+ if (!fAsserted ) \
+ { \
+ _AssertMsg( _exp, _msg, (fAsserted = true), _bFatal ); \
+ } \
+ } while (0)
+#endif
+
+/* Spew macros... */
+
+// AssertFatal macros
+// AssertFatal is used to detect an unrecoverable error condition.
+// If enabled, it may display an assert dialog (if DBGFLAG_ASSERTDLG is turned on or running under the debugger),
+// and always terminates the application
+
+#ifdef DBGFLAG_ASSERTFATAL
+
+#define AssertFatal( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), true )
+#define AssertFatalOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), true )
+#define AssertFatalMsg( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), true )
+#define AssertFatalMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, true )
+#define AssertFatalFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: " _T(#_exp), _f, true )
+#define AssertFatalEquals( _exp, _expectedValue ) AssertFatalMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
+#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) AssertFatalMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
+#define VerifyFatal( _exp ) AssertFatal( _exp )
+#define VerifyEqualsFatal( _exp, _expectedValue ) AssertFatalEquals( _exp, _expectedValue )
+
+#define AssertFatalMsg1( _exp, _msg, a1 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1 )))
+#define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2 )))
+#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3 )))
+#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4 )))
+#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5 )))
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6 )))
+#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7 )))
+#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8 )))
+#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, (const tchar *)(CDbgFmtMsg( _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 )))
+
+#else // DBGFLAG_ASSERTFATAL
+
+#define AssertFatal( _exp ) ((void)0)
+#define AssertFatalOnce( _exp ) ((void)0)
+#define AssertFatalMsg( _exp, _msg ) ((void)0)
+#define AssertFatalMsgOnce( _exp, _msg ) ((void)0)
+#define AssertFatalFunc( _exp, _f ) ((void)0)
+#define AssertFatalEquals( _exp, _expectedValue ) ((void)0)
+#define AssertFatalFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
+#define VerifyFatal( _exp ) (_exp)
+#define VerifyEqualsFatal( _exp, _expectedValue ) (_exp)
+
+#define AssertFatalMsg1( _exp, _msg, a1 ) ((void)0)
+#define AssertFatalMsg2( _exp, _msg, a1, a2 ) ((void)0)
+#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
+#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
+#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
+#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
+#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
+
+#endif // DBGFLAG_ASSERTFATAL
+
+// lightweight assert macros: in theory, can be run in release without slowing it down
+#if defined(_CERT) || defined(_RETAIL)
+#define AssertAligned(PTR)
+#else
+# if defined( _X360 )
+# define AssertAligned(PTR) __twnei( intp(PTR) & 0xF, 0 ) // trap if not equal to immediate value; unsigned comparison
+# elif defined( DBGFLAG_ASSERT )
+# define AssertAligned( adr ) Assert( ( ( ( intp ) ( adr ) ) & 0xf ) == 0 )
+# else
+# define AssertAligned(PTR)
+# endif
+#endif
+
+// Assert macros
+// Assert is used to detect an important but survivable error.
+// It's only turned on when DBGFLAG_ASSERT is true.
+
+#ifdef DBGFLAG_ASSERT
+
+#define Assert( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
+#define AssertMsg_( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false )
+#define AssertOnce( _exp ) _AssertMsgOnce( _exp, _T("Assertion Failed: ") _T(#_exp), false )
+#define AssertMsgOnce( _exp, _msg ) _AssertMsgOnce( _exp, _msg, false )
+#define AssertFunc( _exp, _f ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), _f, false )
+#define AssertEquals( _exp, _expectedValue ) AssertMsg2( (_exp) == (_expectedValue), _T("Expected %d but got %d!"), (_expectedValue), (_exp) )
+#define AssertFloatEquals( _exp, _expectedValue, _tol ) AssertMsg2( fabs((_exp) - (_expectedValue)) <= (_tol), _T("Expected %f but got %f!"), (_expectedValue), (_exp) )
+#define Verify( _exp ) Assert( _exp )
+#define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue )
+
+#define AssertMsg( _exp, _msg ) AssertMsg_( _exp, _T( _msg ) )
+#define AssertMsg1( _exp, _msg, a1 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1 )) )
+#define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2 )) )
+#define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3 )) )
+#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4 )) )
+#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5 )) )
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6 )) )
+#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7 )) )
+#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8 )) )
+#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg_( _exp, (const tchar *)(CDbgFmtMsg( _T( _msg ), a1, a2, a3, a4, a5, a6, a7, a8, a9 )) )
+
+#else // DBGFLAG_ASSERT
+
+#define Assert( _exp ) ((void)0)
+#define AssertOnce( _exp ) ((void)0)
+#define AssertMsg( _exp, _msg ) ((void)0)
+#define AssertMsgOnce( _exp, _msg ) ((void)0)
+#define AssertFunc( _exp, _f ) ((void)0)
+#define AssertEquals( _exp, _expectedValue ) ((void)0)
+#define AssertFloatEquals( _exp, _expectedValue, _tol ) ((void)0)
+#define Verify( _exp ) (_exp)
+#define VerifyEquals( _exp, _expectedValue ) (_exp)
+
+#define AssertMsg1( _exp, _msg, a1 ) ((void)0)
+#define AssertMsg2( _exp, _msg, a1, a2 ) ((void)0)
+#define AssertMsg3( _exp, _msg, a1, a2, a3 ) ((void)0)
+#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) ((void)0)
+#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) ((void)0)
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) ((void)0)
+#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) ((void)0)
+#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) ((void)0)
+#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) ((void)0)
+
+#endif // DBGFLAG_ASSERT
+
+#define STRINGIFY_INTERNAL(x) #x
+#define STRINGIFY(x) STRINGIFY_INTERNAL(x)
+
+#define FILE_LINE_FUNCTION_STRING __FILE__ "(" STRINGIFY(__LINE__) "):" __FUNCTION__ ":"
+#define FILE_LINE_STRING __FILE__ "(" STRINGIFY(__LINE__) "):"
+#define FUNCTION_LINE_STRING __FUNCTION__ "(" STRINGIFY(__LINE__) "): "
+
+
+//////////////////////////////////////////////////////////////////////////
+// Legacy Logging System
+//////////////////////////////////////////////////////////////////////////
+
+// Channels which map the legacy logging system to the new system.
+
+// Channel for all default Msg/Warning/Error commands.
+DECLARE_LOGGING_CHANNEL( LOG_GENERAL );
+// Channel for all asserts.
+DECLARE_LOGGING_CHANNEL( LOG_ASSERT );
+// Channel for all ConMsg and ConColorMsg commands.
+DECLARE_LOGGING_CHANNEL( LOG_CONSOLE );
+// Channel for all DevMsg and DevWarning commands with level < 2.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER );
+// Channel for ConDMsg commands.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_CONSOLE );
+// Channel for all DevMsg and DevWarning commands with level >= 2.
+DECLARE_LOGGING_CHANNEL( LOG_DEVELOPER_VERBOSE );
+
+// Legacy logging functions
+
+PLATFORM_INTERFACE void Error( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void Error_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+#if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+#define Msg( ... ) ((void)0)
+#define Warning( ... ) ((void)0)
+#define Warning_SpewCallStack( ... ) ((void)0)
+#define DevMsg( ... ) ((void)0)
+#define DevWarning( ... ) ((void)0)
+#define ConColorMsg( ... ) ((void)0)
+#define ConMsg( ... ) ((void)0)
+#define ConDMsg( ... ) ((void)0)
+#define COM_TimestampedLog( ... ) ((void)0)
+
+#else // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+PLATFORM_INTERFACE void Msg( const tchar* pMsg, ... );
+PLATFORM_INTERFACE void Warning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void Warning_SpewCallStack( int iMaxCallStackLength, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+#ifdef _PS3
+
+PLATFORM_OVERLOAD void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_OVERLOAD void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+PLATFORM_INTERFACE void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_INTERFACE void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_INTERFACE void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_INTERFACE void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+#else // !_PS3
+
+PLATFORM_INTERFACE void DevMsg( int level, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_INTERFACE void DevWarning( int level, const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+PLATFORM_OVERLOAD void DevMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+PLATFORM_OVERLOAD void DevWarning( const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_OVERLOAD void ConColorMsg( const Color& clr, const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+PLATFORM_OVERLOAD void ConMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // _PS3
+
+PLATFORM_INTERFACE void ConDMsg( const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+PLATFORM_INTERFACE void COM_TimestampedLog( char const *fmt, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // #if defined( DBGFLAG_STRINGS_STRIP ) && !defined( TIER0_DLL_EXPORT )
+
+// You can use this macro like a runtime assert macro.
+// If the condition fails, then Error is called with the message. This macro is called
+// like AssertMsg, where msg must be enclosed in parenthesis:
+//
+// ErrorIfNot( bCondition, ("a b c %d %d %d", 1, 2, 3) );
+#define ErrorIfNot( condition, msg ) \
+ if ( (condition) ) \
+ ; \
+ else \
+ { \
+ Error msg; \
+ }
+
+#ifdef _DEBUG
+#define DebugMsg(...) DevMsg(__VA_ARGS__)
+#else
+#define DebugMsg(...)
+#endif
+
+// @TODO: these callstack spew functions are currently disabled in the new logging system. Need to add support for these if desired.
+PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Enable( bool bEnable );
+PLATFORM_INTERFACE void _Warning_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
+
+PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Enable( bool bEnable );
+PLATFORM_INTERFACE void _Error_AlwaysSpewCallStack_Length( int iMaxCallStackLength );
+
+
+/* Code macros, debugger interface */
+
+#ifdef _DEBUG
+
+#define DBG_CODE( _code ) if (0) ; else { _code }
+#define DBG_CODE_NOSCOPE( _code ) _code
+#define DBG_DCODE( _g, _l, _code ) if (IsSpewActive( _g, _l )) { _code } else {}
+#define DBG_BREAK() DebuggerBreak() /* defined in platform.h */
+
+#else /* not _DEBUG */
+
+#define DBG_CODE( _code ) ((void)0)
+#define DBG_CODE_NOSCOPE( _code )
+#define DBG_DCODE( _g, _l, _code ) ((void)0)
+#define DBG_BREAK() ((void)0)
+
+#endif /* _DEBUG */
+
+//-----------------------------------------------------------------------------
+// Macro to assist in asserting constant invariants during compilation
+
+#ifdef _DEBUG
+#define COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
+#define ASSERT_INVARIANT( pred ) static void UNIQUE_ID() { COMPILE_TIME_ASSERT( pred ) }
+#else
+#define COMPILE_TIME_ASSERT( pred )
+#define ASSERT_INVARIANT( pred )
+#endif
+
+#ifdef _DEBUG
+template<typename DEST_POINTER_TYPE, typename SOURCE_POINTER_TYPE>
+inline DEST_POINTER_TYPE assert_cast(SOURCE_POINTER_TYPE* pSource)
+{
+ Assert( static_cast<DEST_POINTER_TYPE>(pSource) == dynamic_cast<DEST_POINTER_TYPE>(pSource) );
+ return static_cast<DEST_POINTER_TYPE>(pSource);
+}
+#else
+#define assert_cast static_cast
+#endif
+
+//-----------------------------------------------------------------------------
+// Templates to assist in validating pointers:
+
+// Have to use these stubs so we don't have to include windows.h here.
+PLATFORM_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 );
+PLATFORM_INTERFACE void _AssertValidStringPtr( const tchar* ptr, int maxchar );
+
+#ifdef DBGFLAG_ASSERT
+inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { _AssertValidStringPtr( ptr, maxchar ); }
+template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); }
+template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); }
+template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); }
+#define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this))
+
+#else
+
+inline void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF ) { }
+template<class T> inline void AssertValidReadPtr( T* ptr, int count = 1 ) { }
+template<class T> inline void AssertValidWritePtr( T* ptr, int count = 1 ) { }
+template<class T> inline void AssertValidReadWritePtr( T* ptr, int count = 1 ) { }
+#define AssertValidThis()
+#endif
+
+//-----------------------------------------------------------------------------
+// Macro to protect functions that are not reentrant
+
+#ifdef _DEBUG
+class CReentryGuard
+{
+public:
+ CReentryGuard(int *pSemaphore)
+ : m_pSemaphore(pSemaphore)
+ {
+ ++(*m_pSemaphore);
+ }
+
+ ~CReentryGuard()
+ {
+ --(*m_pSemaphore);
+ }
+
+private:
+ int *m_pSemaphore;
+};
+
+#define ASSERT_NO_REENTRY() \
+ static int fSemaphore##__LINE__; \
+ Assert( !fSemaphore##__LINE__ ); \
+ CReentryGuard ReentryGuard##__LINE__( &fSemaphore##__LINE__ )
+#else
+#define ASSERT_NO_REENTRY()
+#endif
+
+// Tier0 uses these for string functions since this abstraction is normally done in tier1.
+#ifdef POSIX
+ #define Tier0Internal_sntprintf snprintf
+ #define Tier0Internal_vsntprintf vsnprintf
+ #define Tier0Internal_vsnprintf vsnprintf
+#else
+ #define Tier0Internal_sntprintf _sntprintf
+ #define Tier0Internal_vsntprintf _vsntprintf
+ #define Tier0Internal_vsnprintf _vsnprintf
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Inline string formatter
+//
+
+#include "tier0/valve_off.h"
+class CDbgFmtMsg
+{
+public:
+ CDbgFmtMsg(const tchar *pszFormat, ...)
+ {
+ va_list arg_ptr;
+
+ va_start(arg_ptr, pszFormat);
+ Tier0Internal_vsntprintf(m_szBuf, sizeof(m_szBuf)-1, pszFormat, arg_ptr);
+ va_end(arg_ptr);
+
+ m_szBuf[sizeof(m_szBuf)-1] = 0;
+ }
+
+ operator const tchar *() const
+ {
+ return m_szBuf;
+ }
+
+private:
+ tchar m_szBuf[256];
+};
+#include "tier0/valve_on.h"
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Embed debug info in each file.
+//
+#if defined( _WIN32 ) && !defined( _X360 )
+
+ #ifdef _DEBUG
+ #pragma comment(compiler)
+ #endif
+
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Wrap around a variable to create a simple place to put a breakpoint
+//
+
+#ifdef _DEBUG
+
+template< class Type >
+class CDataWatcher
+{
+public:
+ const Type& operator=( const Type &val )
+ {
+ return Set( val );
+ }
+
+ const Type& operator=( const CDataWatcher<Type> &val )
+ {
+ return Set( val.m_Value );
+ }
+
+ const Type& Set( const Type &val )
+ {
+ // Put your breakpoint here
+ m_Value = val;
+ return m_Value;
+ }
+
+ Type& GetForModify()
+ {
+ return m_Value;
+ }
+
+ const Type& operator+=( const Type &val )
+ {
+ return Set( m_Value + val );
+ }
+
+ const Type& operator-=( const Type &val )
+ {
+ return Set( m_Value - val );
+ }
+
+ const Type& operator/=( const Type &val )
+ {
+ return Set( m_Value / val );
+ }
+
+ const Type& operator*=( const Type &val )
+ {
+ return Set( m_Value * val );
+ }
+
+ const Type& operator^=( const Type &val )
+ {
+ return Set( m_Value ^ val );
+ }
+
+ const Type& operator|=( const Type &val )
+ {
+ return Set( m_Value | val );
+ }
+
+ const Type& operator++()
+ {
+ return (*this += 1);
+ }
+
+ Type operator--()
+ {
+ return (*this -= 1);
+ }
+
+ Type operator++( int ) // postfix version..
+ {
+ Type val = m_Value;
+ (*this += 1);
+ return val;
+ }
+
+ Type operator--( int ) // postfix version..
+ {
+ Type val = m_Value;
+ (*this -= 1);
+ return val;
+ }
+
+ // For some reason the compiler only generates type conversion warnings for this operator when used like
+ // CNetworkVarBase<unsigned tchar> = 0x1
+ // (it warns about converting from an int to an unsigned char).
+ template< class C >
+ const Type& operator&=( C val )
+ {
+ return Set( m_Value & val );
+ }
+
+ operator const Type&() const
+ {
+ return m_Value;
+ }
+
+ const Type& Get() const
+ {
+ return m_Value;
+ }
+
+ const Type* operator->() const
+ {
+ return &m_Value;
+ }
+
+ Type m_Value;
+
+};
+
+#else
+
+template< class Type >
+class CDataWatcher
+{
+private:
+ CDataWatcher(); // refuse to compile in non-debug builds
+};
+
+#endif
+
+// Code for programmatically setting/unsetting hardware breakpoints (there's probably a 360 and
+#ifdef IS_WINDOWS_PC
+
+typedef void * HardwareBreakpointHandle_t;
+
+enum EHardwareBreakpointType
+{
+ BREAKPOINT_EXECUTE = 0,
+ BREAKPOINT_WRITE,
+ BREAKPOINT_READWRITE,
+};
+
+enum EHardwareBreakpointSize
+{
+ BREAKPOINT_SIZE_1 = 1,
+ BREAKPOINT_SIZE_2 = 2,
+ BREAKPOINT_SIZE_4 = 4,
+ BREAKPOINT_SIZE_8 = 8,
+};
+
+PLATFORM_INTERFACE HardwareBreakpointHandle_t SetHardwareBreakpoint( EHardwareBreakpointType eType, EHardwareBreakpointSize eSize, const void *pvLocation );
+PLATFORM_INTERFACE bool ClearHardwareBreakpoint( HardwareBreakpointHandle_t handle );
+
+class CHardwareBreakPointScopeGuard
+{
+public:
+ CHardwareBreakPointScopeGuard( const void *pvLocation, size_t nLocationSize, EHardwareBreakpointType eType = BREAKPOINT_WRITE )
+ {
+ EHardwareBreakpointSize eSize = BREAKPOINT_SIZE_4;
+ switch ( nLocationSize )
+ {
+ case 1:
+ eSize = BREAKPOINT_SIZE_1;
+ break;
+ case 2:
+ eSize = BREAKPOINT_SIZE_2;
+ break;
+ case 4:
+ eSize = BREAKPOINT_SIZE_4;
+ break;
+ case 8:
+ eSize = BREAKPOINT_SIZE_8;
+ break;
+ default:
+ Warning( _T( "SetHardwareBreakpoint can only work with 1, 2, 4 or 8 byte data fields." ) );
+ break;
+ }
+
+ m_hBreakPoint = SetHardwareBreakpoint( eType, eSize, pvLocation );
+ m_bActive = m_hBreakPoint != (HardwareBreakpointHandle_t)0;
+ }
+
+ ~CHardwareBreakPointScopeGuard()
+ {
+ Release();
+ }
+
+ void Release()
+ {
+ if ( !m_bActive )
+ return;
+ ClearHardwareBreakpoint( m_hBreakPoint );
+ }
+
+private:
+ bool m_bActive;
+ HardwareBreakpointHandle_t m_hBreakPoint;
+};
+
+#endif // IS_WINDOWS_PC
+//-----------------------------------------------------------------------------
+
+#endif /* DBG_H */
diff --git a/external/vpc/public/tier0/dbgflag.h b/external/vpc/public/tier0/dbgflag.h
new file mode 100644
index 0000000..deee3e5
--- /dev/null
+++ b/external/vpc/public/tier0/dbgflag.h
@@ -0,0 +1,68 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This file sets all of our debugging flags. It should be
+// called before all other header files.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef DBGFLAG_H
+#define DBGFLAG_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+// Here are all the flags we support:
+// DBGFLAG_MEMORY: Enables our memory debugging system, which overrides malloc & free
+// DBGFLAG_MEMORY_NEWDEL: Enables new / delete tracking for memory debug system. Requires DBGFLAG_MEMORY to be enabled.
+// DBGFLAG_VALIDATE: Enables our recursive validation system for checking integrity and memory leaks
+// DBGFLAG_ASSERT: Turns Assert on or off (when off, it isn't compiled at all)
+// DBGFLAG_ASSERTFATAL: Turns AssertFatal on or off (when off, it isn't compiled at all)
+// DBGFLAG_ASSERTDLG: Turns assert dialogs on or off and debug breaks on or off when not under the debugger.
+// (Dialogs will always be on when process is being debugged.)
+// DBGFLAG_STRINGS: Turns on hardcore string validation (slow but safe)
+
+#undef DBGFLAG_MEMORY
+#undef DBGFLAG_MEMORY_NEWDEL
+#undef DBGFLAG_VALIDATE
+#undef DBGFLAG_ASSERT
+#undef DBGFLAG_ASSERTFATAL
+#undef DBGFLAG_ASSERTDLG
+#undef DBGFLAG_STRINGS
+
+//-----------------------------------------------------------------------------
+// Default flags for debug builds
+//-----------------------------------------------------------------------------
+#if defined( _DEBUG ) && !defined( PS3MEMOVERRIDEWRAP )
+
+#define DBGFLAG_MEMORY
+#ifdef _SERVER // only enable new & delete tracking for server; on client it conflicts with CRT mem leak tracking
+#define DBGFLAG_MEMORY_NEWDEL
+#endif
+#ifdef STEAM
+#define DBGFLAG_VALIDATE
+#endif
+#define DBGFLAG_ASSERT
+#define DBGFLAG_ASSERTFATAL
+#define DBGFLAG_ASSERTDLG
+#define DBGFLAG_STRINGS
+
+
+//-----------------------------------------------------------------------------
+// Default flags for release builds
+//-----------------------------------------------------------------------------
+#else // _DEBUG
+#ifdef STEAM
+#define DBGFLAG_ASSERT
+#endif
+#define DBGFLAG_ASSERTFATAL // note: fatal asserts are enabled in release builds
+#define DBGFLAG_ASSERTDLG
+
+#endif // _DEBUG
+
+#if defined( _CERT )
+#define DBGFLAG_STRINGS_STRIP
+#endif
+
+#endif // DBGFLAG_H
diff --git a/external/vpc/public/tier0/etwprof.h b/external/vpc/public/tier0/etwprof.h
new file mode 100644
index 0000000..ba9f8f5
--- /dev/null
+++ b/external/vpc/public/tier0/etwprof.h
@@ -0,0 +1,155 @@
+//============ Copyright (c) Valve Corporation, All rights reserved. ============
+//
+// ETW (Event Tracing for Windows) profiling helpers.
+// This allows easy insertion of Generic Event markers into ETW/xperf tracing
+// which then aids in analyzing the traces and finding performance problems.
+// The usage patterns are to use ETWBegin and ETWEnd (typically through the
+// convenience class CETWScope) to bracket time-consuming operations. In addition
+// ETWFrameMark marks the beginning of each frame, and ETWMark can be used to
+// mark other notable events. More event types and providers can be added as needed.
+// When recording xperf profiles add Valve-Main+Valve-FrameRate to the list of
+// user-mode providers and be sure to register the providers with this sequence
+// of commands:
+// xcopy /y game\bin\tier0.dll %temp%
+// wevtutil um src\tier0\ValveETWProvider.man
+// wevtutil im src\tier0\ValveETWProvider.man
+//
+//===============================================================================
+
+#ifndef ETWPROF_H
+#define ETWPROF_H
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+#ifdef IS_WINDOWS_PC
+// ETW support should be compiled in for all Windows PC platforms. It isn't
+// supported on Windows XP but that is determined at run-time.
+#if !defined(STANDALONE_VPC)
+#define ETW_MARKS_ENABLED
+#endif
+#endif
+
+#ifdef ETW_MARKS_ENABLED
+
+// Insert a single event to mark a point in an ETW trace. The return value is a 64-bit
+// time stamp.
+PLATFORM_INTERFACE int64 ETWMark( const char *pMessage );
+// Optionally do full printf formatting of the mark string. This will be more expensive,
+// but only when tracing is enabled.
+PLATFORM_INTERFACE int64 ETWMarkPrintf( PRINTF_FORMAT_STRING const char *pMessage, ... ) FMTFUNCTION( 1, 2 );
+// Optionally specify one to four floats. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1F( const char *pMessage, float data1 );
+PLATFORM_INTERFACE void ETWMark2F( const char *pMessage, float data1, float data2 );
+PLATFORM_INTERFACE void ETWMark3F( const char *pMessage, float data1, float data2, float data3 );
+PLATFORM_INTERFACE void ETWMark4F( const char *pMessage, float data1, float data2, float data3, float data4 );
+// Optionally specify one to four ints. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1I( const char *pMessage, int data1 );
+PLATFORM_INTERFACE void ETWMark2I( const char *pMessage, int data1, int data2 );
+PLATFORM_INTERFACE void ETWMark3I( const char *pMessage, int data1, int data2, int data3 );
+PLATFORM_INTERFACE void ETWMark4I( const char *pMessage, int data1, int data2, int data3, int data4 );
+// Optionally specify one to two strings. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+PLATFORM_INTERFACE void ETWMark1S( const char *pMessage, const char* data1 );
+PLATFORM_INTERFACE void ETWMark2S( const char *pMessage, const char* data1, const char* data2 );
+
+// Insert a begin event to mark the start of some work. The return value is a 64-bit
+// time stamp which should be passed to the corresponding ETWEnd function.
+PLATFORM_INTERFACE int64 ETWBegin( const char *pMessage );
+
+// Insert a paired end event to mark the end of some work.
+PLATFORM_INTERFACE int64 ETWEnd( const char *pMessage, int64 nStartTime );
+
+// Mark the start of the next render frame. bIsServerProcess must be passed
+// in consistently for a particular process.
+PLATFORM_INTERFACE void ETWRenderFrameMark( bool bIsServerProcess );
+// Mark the start of the next simulation frame. bIsServerProcess must be passed
+// in consistently for a particular process.
+PLATFORM_INTERFACE void ETWSimFrameMark( bool bIsServerProcess );
+// Return the frame number recorded in the ETW trace -- useful for synchronization
+// other profile information to the ETW trace.
+PLATFORM_INTERFACE int ETWGetRenderFrameNumber();
+
+PLATFORM_INTERFACE void ETWMouseDown( int nWhichButton, int nX, int nY );
+PLATFORM_INTERFACE void ETWMouseUp( int nWhichButton, int nX, int nY );
+PLATFORM_INTERFACE void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar );
+
+PLATFORM_INTERFACE void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck );
+PLATFORM_INTERFACE void ETWThrottled();
+PLATFORM_INTERFACE void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck );
+
+// This class calls the ETW Begin and End functions in order to insert a
+// pair of events to bracket some work.
+class CETWScope
+{
+public:
+ CETWScope( const char *pMessage )
+ : m_pMessage( pMessage )
+ {
+ m_nStartTime = ETWBegin( pMessage );
+ }
+ ~CETWScope()
+ {
+ ETWEnd( m_pMessage, m_nStartTime );
+ }
+private:
+ // Private and unimplemented to disable copying.
+ CETWScope( const CETWScope& rhs );
+ CETWScope& operator=( const CETWScope& rhs );
+
+ const char* m_pMessage;
+ int64 m_nStartTime;
+};
+
+#else
+
+inline int64 ETWMark( const char* ) { return 0; }
+inline int64 ETWMarkPrintf( const char *, ... ) { return 0; }
+inline void ETWMark1F( const char *, float ) { }
+inline void ETWMark2F( const char *, float , float ) { }
+inline void ETWMark3F( const char *, float , float , float ) { }
+inline void ETWMark4F( const char *, float , float , float , float ) { }
+inline void ETWMark1I( const char *, int ) { }
+inline void ETWMark2I( const char *, int , int ) { }
+inline void ETWMark3I( const char *, int , int , int ) { }
+inline void ETWMark4I( const char *, int , int , int , int ) { }
+// Optionally specify one to two strings. They will show up in separate columns in
+// summary tables to allow sorting and easier transfer to spreadsheets.
+inline void ETWMark1S( const char *, const char* ) { }
+inline void ETWMark2S( const char *, const char* , const char* ) { }
+
+inline int64 ETWBegin( const char* ) { return 0; }
+inline int64 ETWEnd( const char*, int64 ) { return 0; }
+inline void ETWRenderFrameMark( bool ) {}
+inline void ETWSimFrameMark( bool ) {}
+inline int ETWGetRenderFrameNumber() { return 0; }
+
+inline void ETWMouseDown( int nWhichButton, int nX, int nY ) {}
+inline void ETWMouseUp( int nWhichButton, int nX, int nY ) {}
+inline void ETWKeyDown( int nScanCode, int nVirtualCode, const char *pChar ) {}
+
+inline void ETWSendPacket( const char *pTo, int nWireSize, int nOutSequenceNR, int nOutSequenceNrAck ) {}
+inline void ETWThrottled() {}
+inline void ETWReadPacket( const char *pFrom, int nWireSize, int nInSequenceNR, int nOutSequenceNRAck ) {}
+
+// This class calls the ETW Begin and End functions in order to insert a
+// pair of events to bracket some work.
+class CETWScope
+{
+public:
+ CETWScope( const char* )
+ {
+ }
+private:
+ // Private and unimplemented to disable copying.
+ CETWScope( const CETWScope& rhs );
+ CETWScope& operator=( const CETWScope& rhs );
+};
+
+#endif
+
+#endif // ETWPROF_H
diff --git a/external/vpc/public/tier0/eventmasks.h b/external/vpc/public/tier0/eventmasks.h
new file mode 100644
index 0000000..4774809
--- /dev/null
+++ b/external/vpc/public/tier0/eventmasks.h
@@ -0,0 +1,480 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#pragma once
+
+typedef union EVENT_MASK(TC_deliver_mode)
+{
+ struct
+ {
+ uint16 DD:1; // both logical processors in deliver mode },
+ uint16 DB:1; // logical processor 0 in deliver mode, 1 in build mode },
+ uint16 DI:1; // logical processor 0 in deliver mode, 1 is inactive },
+ uint16 BD:1; // logical processor 0 in build mode, 1 in deliver mode },
+ uint16 BB:1; // both logical processors in build mode },
+ uint16 BI:1; // logical processor 0 in build mode, 1 is inactive },
+ uint16 ID:1; // logical processor 0 is inactive, 1 in deliver mode },
+ uint16 IB:1; // logical processor 0 is inactive, 1 in build mode }
+ };
+ uint16 flat;
+} EVENT_MASK(TC_deliver_mode);
+
+typedef union EVENT_MASK(BPU_fetch_request)
+{
+
+ struct
+ {
+ uint16 TCMISS:1; // Trace cache lookup miss },
+ };
+ uint16 flat;
+} EVENT_MASK(BPU_fetch_request);
+
+
+typedef union EVENT_MASK(ITLB_reference)
+{
+ struct
+ {
+ uint16 HIT : 1; //ITLB hit },
+ uint16 MISS : 1;//ITLB miss },
+ uint16 HIT_UC :1; // Uncacheable ITLB hit }
+ };
+ uint16 flat;
+} EVENT_MASK(ITLB_reference);
+
+typedef union EVENT_MASK(memory_cancel)
+{
+ struct
+ {
+ uint16 dummy : 2;
+
+ uint16 ST_RB_FULL:1; //Replayed because no store request buffer is available },
+ uint16 _64K_CONF:1; //Conflicts due to 64K aliasing }
+ };
+ uint16 flat;
+}EVENT_MASK(memory_cancel);
+
+typedef union EVENT_MASK(memory_complete)
+{
+ struct
+ {
+ uint16 LSC:1; // Load split completed, excluding UC/WC loads },
+ uint16 SSC:1; //Any split stores completed } }
+ };
+ uint16 flat;
+} EVENT_MASK(memory_complete);
+
+typedef union EVENT_MASK(load_port_replay)
+{
+ struct
+ {
+ uint16 dummy:1;
+ uint16 SPLIT_LD:1; //Split load } }
+ };
+ uint16 flat;
+} EVENT_MASK(load_port_replay);
+
+typedef union EVENT_MASK(store_port_replay)
+{
+ struct
+ {
+ uint16 dummy0:1;
+ uint16 SPLIT_ST:1; //Split store } }
+
+ };
+ uint16 flat;
+} EVENT_MASK(store_port_replay);
+
+typedef union EVENT_MASK(MOB_load_replay)
+{
+ struct
+ {
+ uint16 dummy0:1;
+
+ uint16 NO_STA:1; //Replayed because of unknown store address },
+
+ uint16 dummy2:1;
+
+ uint16 NO_STD:1; //Replayed because of unknown store data },
+ uint16 PARTIAL_DATA:1; //Replayed because of partially overlapped data access between the load and store operations },
+ uint16 UNALGN_ADDR:1; //Replayed because the lower 4 bits of the linear address do not match between the load and store operations } }
+ };
+ uint16 flat;
+}EVENT_MASK(MOB_load_replay);
+
+typedef union EVENT_MASK(page_walk_type)
+{
+ struct
+ {
+ uint16 DTMISS:1; // Page walk for a data TLB miss },
+ uint16 ITMISS:1; // Page walk for an instruction TLB miss } }
+ };
+ uint16 flat;
+}EVENT_MASK(page_walk_type);
+
+
+typedef union EVENT_MASK(BSQ_cache_reference)
+{
+ struct
+ {
+ uint16 RD_2ndL_HITS:1; // Read 2nd level cache hit Shared },
+ uint16 RD_2ndL_HITE:1; // Read 2nd level cache hit Exclusive },
+ uint16 RD_2ndL_HITM:1; // Read 2nd level cache hit Modified },
+ uint16 RD_3rdL_HITS:1; // Read 3rd level cache hit Shared },
+ uint16 RD_3rdL_HITE:1; // Read 3rd level cache hit Exclusive },
+ uint16 RD_3rdL_HITM:1; // Read 3rd level cache hit Modified },
+ uint16 dummy6:1;
+ uint16 dummy7:1;
+ uint16 RD_2ndL_MISS:1; // Read 2nd level cache miss },
+ uint16 RD_3rdL_MISS:1; // Read 3rd level cache miss },
+ uint16 WR_2ndL_MISS:1; // Writeback lookup from DAC misses the 2nd level cache } }
+ };
+ uint16 flat;
+} EVENT_MASK(BSQ_cache_reference) ;
+
+typedef union EVENT_MASK(IOQ)
+{
+ struct
+ {
+ uint16 bit0:1; // bus request type (use 00001 for invalid or default)
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ uint16 bit3:1; //
+ uint16 bit4:1; //
+ uint16 ALL_READ:1; // Count read entries },
+ uint16 ALL_WRITE:1; // Count write entries },
+ uint16 MEM_UC:1; // Count UC memory access entries },
+ uint16 MEM_WC:1; // Count WC memory access entries },
+ uint16 MEM_WT:1; // Count WT memory access entries },
+ uint16 MEM_WP:1; // Count WP memory access entries },
+ uint16 MEM_WB:1; // Count WB memory access entries },
+ uint16 dummy12:1;
+
+ uint16 OWN:1; // Count own store requests },
+ uint16 OTHER:1; // Count other and DMA store requests },
+ uint16 PREFETCH:1; // Include HW and SW prefetch requests } }
+ };
+ uint16 flat;
+} EVENT_MASK(IOQ) ;
+
+typedef union EVENT_MASK(FSB_data_activity)
+{
+ struct
+ {
+ /* DRDY_OWN is mutually exclusive with DRDY_OTHER */
+ /* DBSY_OWN is mutually exclusive with DBSY_OTHER */
+ uint16 DRDY_DRV:1; // Count when this processor drives data onto the bus },
+ uint16 DRDY_OWN:1; // Count when this processor reads data from the bus },
+ uint16 DRDY_OTHER:1; // Count when data is on the bus but not being sampled by the processor },
+ uint16 DBSY_DRV:1; // Count when this processor reserves the bus for driving data },
+ uint16 DBSY_OWN:1; // Count when this processor reserves the bus for sampling data },
+ uint16 DBSY_OTHER:1; // Count when the bus is reserved for driving data this processor will not sample } }
+ };
+ uint16 flat;
+}EVENT_MASK(FSB_data_activity);
+
+typedef union EVENT_MASK(BSQ)
+{
+ struct
+ {
+ uint16 REQ_TYPE0:1; // Request type encoding bit 0 },
+ uint16 REQ_TYPE1:1; // Request type encoding bit 1 },
+ uint16 REQ_LEN0:1; // Request length encoding bit 0 },
+ uint16 REQ_LEN1:1; // Request length encoding bit 1 },
+ uint16 dummy4: 1;
+ uint16 REQ_IO_TYPE:1; // Request type is input or output },
+ uint16 REQ_LOCK_TYPE:1; // Request type is bus lock },
+ uint16 REQ_CACHE_TYPE:1; // Request type is cacheable },
+ uint16 REQ_SPLIT_TYPE:1; // Request type is a bus 8-byte chunk split across 8-byte boundary },
+ uint16 REQ_DEM_TYPE:1; // Request type is a demand (1) or prefetch (0) },
+ uint16 REQ_ORD_TYPE:1; // Request is an ordered type },
+ uint16 MEM_TYPE0:1; // Memory type encoding bit 0 },
+ uint16 MEM_TYPE1:1; // Memory type encoding bit 1 },
+ uint16 MEM_TYPE2:1; // Memory type encoding bit 2 } }
+ };
+ uint16 flat;
+} EVENT_MASK(BSQ);
+
+typedef union EVENT_MASK(firm_uop)
+{
+ struct
+ {
+ uint16 dummy15 : 15;
+ uint16 ALL:1; // count all uops of this type } }
+ };
+ uint16 flat;
+} EVENT_MASK(firm_uop);
+
+
+
+typedef union EVENT_MASK(TC_misc)
+{
+ struct
+ {
+ uint16 dymmy4 : 4;
+ uint16 FLUSH:1; // Number of flushes } }
+ };
+ uint16 flat;
+} EVENT_MASK(TC_misc);
+
+typedef union EVENT_MASK(global_power_events)
+{
+ struct
+ {
+ uint16 Running:1; // The processor is active } }
+ };
+ uint16 flat;
+} EVENT_MASK(global_power_events);
+
+typedef union EVENT_MASK(tc_ms_xfer)
+{
+ struct
+ {
+ uint16 CISC:1; // A TC to MS transfer ocurred } }
+ };
+ uint16 flat;
+}EVENT_MASK(tc_ms_xfer);
+
+
+
+typedef union EVENT_MASK(uop_queue_writes)
+{
+ struct
+ {
+ uint16 FROM_TC_BUILD:1; // uops written from TC build mode
+ uint16 FROM_TC_DELIVER:1; // uops written from TC deliver mode
+ uint16 FROM_ROM:1; // uops written from microcode ROM } }
+ };
+ uint16 flat;
+} EVENT_MASK(uop_queue_writes);
+
+typedef union EVENT_MASK(branch_type)
+{
+ struct
+ {
+ uint16 dummy : 1;
+ uint16 CONDITIONAL:1; // Conditional jumps
+ uint16 CALL:1; // Direct or indirect call
+ uint16 RETURN:1; // Return branches
+ uint16 INDIRECT:1; // Returns, indirect calls, or indirect jumps
+ };
+ uint16 flat;
+} EVENT_MASK(branch_type);
+
+
+
+typedef union EVENT_MASK(resource_stall)
+{
+ struct
+ {
+ uint16 dummy1 : 5;
+ uint16 SBFULL:1; // A Stall due to lack of store buffers } }
+ };
+ uint16 flat;
+} EVENT_MASK(resource_stall);
+
+
+
+
+typedef union EVENT_MASK(WC_Buffer)
+{
+ struct
+ {
+ uint16 WCB_EVICTS : 1; // all causes },
+ uint16 WCB_FULL_EVICT : 1; // no WC buffer is available },
+ /* XXX: 245472-011 no longer lists bit 2, but that looks like
+ a table formatting error. Keeping it for now. */
+ uint16 WCB_HITM_EVICT : 1; // store encountered a Hit Modified condition } }
+ };
+ uint16 flat;
+} EVENT_MASK(WC_Buffer);
+
+
+typedef union EVENT_MASK(b2b_cycles)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 bit1 : 1; //
+ uint16 bit2 : 1; //
+ uint16 bit3 : 1; //
+ uint16 bit4 : 1; //
+ uint16 bit5 : 1; //
+ uint16 bit6 : 1; //
+
+ };
+ uint16 flat;
+} EVENT_MASK(b2b_cycles);
+
+typedef union EVENT_MASK(bnr)
+{
+ struct
+ {
+ uint16 bit0:1; //
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(bnr);
+
+
+typedef union EVENT_MASK(snoop)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 dummy1 : 1;
+
+ uint16 bit2:1; //
+ uint16 dummy3:1; //
+ uint16 dummy4:1; //
+ uint16 dummy5:1; //
+ uint16 bit6:1; //
+ uint16 bit7:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(snoop);
+
+
+typedef union EVENT_MASK(response)
+{
+ struct
+ {
+ uint16 dummy0:1; //
+ uint16 bit1:1; //
+ uint16 bit2:1; //
+ uint16 dummy3:1; //
+ uint16 dummy4:1; //
+ uint16 dummy5:1; //
+ uint16 dummy6:1; //
+ uint16 dummy7:1; //
+ uint16 bit8:1; //
+ uint16 bit9:1; //
+ };
+ uint16 flat;
+} EVENT_MASK(response);
+
+
+typedef union EVENT_MASK(nbogus_bogus)
+{
+ struct
+ {
+ uint16 NBOGUS:1; // The marked uops are not bogus
+ uint16 BOGUS:1; // The marked uops are bogus
+ };
+ uint16 flat;
+} EVENT_MASK(nbogus_bogus);
+
+
+typedef union EVENT_MASK(execution_event)
+{
+ struct
+ {
+ uint16 NBOGUS0:1; // non-bogus uops with tag bit 0 set },
+ uint16 NBOGUS1:1; // non-bogus uops with tag bit 1 set },
+ uint16 NBOGUS2:1; // non-bogus uops with tag bit 2 set },
+ uint16 NBOGUS3:1; // non-bogus uops with tag bit 3 set },
+ uint16 BOGUS0:1; // bogus uops with tag bit 0 set },
+ uint16 BOGUS1:1; // bogus uops with tag bit 1 set },
+ uint16 BOGUS2:1; // bogus uops with tag bit 2 set },
+ uint16 BOGUS3:1; // bogus uops with tag bit 3 set } }
+ };
+ uint16 flat;
+}EVENT_MASK(execution_event);
+
+typedef union EVENT_MASK(instr_retired)
+{
+ struct
+ {
+ uint16 NBOGUSNTAG:1; // Non-bogus instructions that are not tagged },
+ uint16 NBOGUSTAG:1; // Non-bogus instructions that are tagged },
+ uint16 BOGUSNTAG:1; // Bogus instructions that are not tagged },
+ uint16 BOGUSTAG:1; // Bogus instructions that are tagged } }
+ };
+ uint16 flat;
+} EVENT_MASK(instr_retired);
+
+
+typedef union EVENT_MASK(uop_type)
+{
+ struct
+ {
+ uint16 dummy0 : 1;
+ uint16 TAGLOADS:1; // The uop is a load operation },
+ uint16 TAGSTORES:1; // The uop is a store operation } }
+ };
+ uint16 flat;
+} EVENT_MASK(uop_type);
+
+typedef union EVENT_MASK(branch_retired)
+{
+ struct
+ {
+ uint16 MMNP:1; // Branch Not-taken Predicted
+ uint16 MMNM:1; // Branch Not-taken Mispredicted
+ uint16 MMTP:1; // Branch Taken Predicted
+ uint16 MMTM:1; // Branch Taken Mispredicted
+ };
+ uint16 flat;
+} EVENT_MASK(branch_retired);
+
+typedef union EVENT_MASK(mispred_branch_retired)
+{
+ struct
+ {
+ uint16 NBOGUS:1; // The retired branch is not bogus } }
+ };
+ uint16 flat;
+} EVENT_MASK(mispred_branch_retired);
+
+
+typedef union EVENT_MASK(x87_assist)
+{
+ struct
+ {
+ uint16 FPSU:1; // FP stack underflow },
+ uint16 FPSO:1; // FP stack overflow },
+ uint16 POAO:1; // x87 output overflow },
+ uint16 POAU:1; // x87 output underflow },
+ uint16 PREA:1; // x87 input assist } }
+ };
+ uint16 flat;
+}EVENT_MASK(x87_assist);
+
+typedef union EVENT_MASK(machine_clear)
+{
+ struct
+ {
+ uint16 CLEAR:1; // Count a portion of the cycles when the machine is cleared },
+ uint16 dummy1: 1;
+ uint16 MOCLEAR:1; // Count clears due to memory ordering issues },
+ uint16 dummy3: 1;
+ uint16 dummy4: 1;
+ uint16 dummy5: 1;
+
+ uint16 SMCLEAR:1;// Count clears due to self-modifying code issues } }
+ };
+ uint16 flat;
+} EVENT_MASK(machine_clear);
+
+
+typedef union EVENT_MASK(x87_SIMD_moves_uop)
+{
+ struct
+ {
+ uint16 dummy3:3;
+ uint16 ALLP0:1; // Count all x87/SIMD store/move uops },
+ uint16 ALLP2:1; // count all x87/SIMD load uops } }
+ };
+ uint16 flat;
+} EVENT_MASK(x87_SIMD_moves_uop);
+
+
+
+
+
+
+
diff --git a/external/vpc/public/tier0/eventmodes.h b/external/vpc/public/tier0/eventmodes.h
new file mode 100644
index 0000000..05e5b21
--- /dev/null
+++ b/external/vpc/public/tier0/eventmodes.h
@@ -0,0 +1,1787 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef EVENTMODES_H
+#define EVENTMODES_H
+
+
+#pragma once
+
+/*
+
+
+
+ Event Modes to choose from:
+
+ P4Event_TC_deliver_mode
+
+ P4Event_BPU_fetch_request
+
+ P4Event_ITLB_reference
+
+ P4Event_memory_cancel
+
+ P4Event_memory_complete
+
+ P4Event_load_port_replay
+
+ P4Event_store_port_replay
+
+ P4Event_MOB_load_replay
+
+ P4Event_page_walk_type
+
+ P4Event_BSQ_cache_reference
+
+ P4Event_IOQ_allocation
+
+ P4Event_IOQ_active_entries
+
+ P4Event_FSB_data_activity
+
+ P4Event_BSQ_allocation
+
+ P4Event_BSQ_active_entries
+
+ P4Event_SSE_input_assist
+
+ P4Event_packed_SP_uop
+
+ P4Event_packed_DP_uop
+
+ P4Event_scalar_SP_uop
+
+ P4Event_scalar_DP_uop
+
+ P4Event_64bit_MMX_uop
+
+ P4Event_128bit_MMX_uop
+
+ P4Event_x87_FP_uop
+
+ P4Event_x87_SIMD_moves_uop
+
+ P4Event_TC_misc
+
+ P4Event_global_power_events
+
+ P4Event_tc_ms_xfer
+
+ P4Event_uop_queue_writes
+
+ P4Event_retired_mispred_branch_type
+
+ P4Event_retired_branch_type
+
+ P4Event_resource_stall
+
+ P4Event_WC_Buffer
+
+ P4Event_b2b_cycles
+
+ P4Event_bnr
+
+ P4Event_snoop
+
+ P4Event_response
+
+ P4Event_front_end_event
+
+ P4Event_execution_event
+
+ P4Event_replay_event
+
+ P4Event_instr_retired
+
+ P4Event_uops_retired
+
+ P4Event_uop_type
+
+ P4Event_branch_retired
+
+ P4Event_mispred_branch_retired
+
+ P4Event_x87_assist
+
+ P4Event_machine_clear
+
+
+*/
+
+
+
+class P4P4Event_TC_deliver_mode: public P4BaseEvent
+{
+public:
+ EVENT_MASK(TC_deliver_mode) * eventMask;
+
+ P4P4Event_TC_deliver_mode()
+ {
+ eventMask = (EVENT_MASK(TC_deliver_mode) *)&m_eventMask;
+
+ escr.ESCREventSelect = 0x01;
+ cccr.CCCRSelect = 0x01;
+ //// eventType = EVENT_TYPE(TC_deliver_mode);
+ description = _T("TC_deliver_mode");
+ UseCounter4();
+ }
+
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+
+class P4P4Event_BPU_fetch_request: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BPU_fetch_request)* eventMask;
+
+ P4P4Event_BPU_fetch_request()
+ {
+ eventMask = (EVENT_MASK(BPU_fetch_request) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x00;
+ // eventType = EVENT_TYPE(BPU_fetch_request);
+ description=_T("BPU_fetch_request");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+
+};
+class P4P4Event_ITLB_reference: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(ITLB_reference) * eventMask;
+
+ P4P4Event_ITLB_reference()
+ {
+ eventMask = (EVENT_MASK(ITLB_reference) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x18;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(ITLB_reference);
+ description=_T("ITLB_reference");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_memory_cancel: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(memory_cancel) * eventMask;
+
+ P4Event_memory_cancel()
+ {
+ eventMask = (EVENT_MASK(memory_cancel) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(memory_cancel);
+ description=_T("memory_cancel");
+ UseCounter8();
+ }
+
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_memory_complete: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(memory_complete) * eventMask;
+
+ P4Event_memory_complete()
+ {
+ eventMask = (EVENT_MASK(memory_complete) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(memory_complete);
+ description=_T("memory_complete");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_load_port_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(load_port_replay) * eventMask;
+
+ P4Event_load_port_replay()
+ {
+ eventMask = (EVENT_MASK(load_port_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(load_port_replay);
+ description=_T("load_port_replay");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_store_port_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(store_port_replay) * eventMask;
+
+ P4Event_store_port_replay()
+ {
+ eventMask = (EVENT_MASK(store_port_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(store_port_replay);
+ description=_T("store_port_replay");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_MOB_load_replay: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(MOB_load_replay) * eventMask;
+
+ P4Event_MOB_load_replay()
+ {
+ eventMask = (EVENT_MASK(MOB_load_replay) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(MOB_load_replay);
+ description=_T("MOB_load_replay");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_page_walk_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(page_walk_type) * eventMask;
+
+ P4Event_page_walk_type()
+ {
+ eventMask = (EVENT_MASK(page_walk_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(page_walk_type);
+ description=_T("page_walk_type");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_BSQ_cache_reference: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ_cache_reference) * eventMask;
+
+ P4Event_BSQ_cache_reference()
+ {
+ eventMask = (EVENT_MASK(BSQ_cache_reference) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ_cache_reference);
+ description=_T("BSQ_cache_reference");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_IOQ_allocation: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(IOQ) * eventMask;
+
+ P4Event_IOQ_allocation()
+ {
+ eventMask = (EVENT_MASK(IOQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(IOQ);
+ description=_T("IOQ_allocation");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_IOQ_active_entries: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(IOQ) * eventMask;
+
+ P4Event_IOQ_active_entries()
+ {
+ eventMask = (EVENT_MASK(IOQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x1A;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(IOQ);
+ description=_T("IOQ_active_entries");
+ UseCounter2();
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_FSB_data_activity: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(FSB_data_activity) * eventMask;
+
+ P4Event_FSB_data_activity()
+ {
+ eventMask = (EVENT_MASK(FSB_data_activity) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x17;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(FSB_data_activity);
+ description=_T("FSB_data_activity");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_BSQ_allocation: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ) * eventMask;
+
+ P4Event_BSQ_allocation()
+ {
+ eventMask = (EVENT_MASK(BSQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ);
+ description=_T("BSQ_allocation");
+ UseCounter0();
+ }
+
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+
+ }
+};
+class P4Event_BSQ_active_entries: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(BSQ) * eventMask;
+
+ P4Event_BSQ_active_entries()
+ {
+ eventMask = (EVENT_MASK(BSQ) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x07;
+ // eventType=EVENT_TYPE(BSQ);
+ description=_T("bsq_active_entries");
+ UseCounter2();
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_SSE_input_assist: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_SSE_input_assist()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x34;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("SSE_input_assist");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_packed_SP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_packed_SP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("packed_SP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_packed_DP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_packed_DP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("packed_DP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_scalar_SP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_scalar_SP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0A;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("scalar_SP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_scalar_DP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_scalar_DP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0E;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("scalar_DP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_64bit_MMX_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_64bit_MMX_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("64bit_MMX_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_128bit_MMX_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_128bit_MMX_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x1A;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("128bit_MMX_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_x87_FP_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(firm_uop) * eventMask;
+
+ P4Event_x87_FP_uop()
+ {
+ eventMask = (EVENT_MASK(firm_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(firm_uop);
+ description=_T("x87_FP_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_x87_SIMD_moves_uop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(x87_SIMD_moves_uop) * eventMask;
+
+ P4Event_x87_SIMD_moves_uop()
+ {
+ eventMask = (EVENT_MASK(x87_SIMD_moves_uop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x2E;
+ cccr.CCCRSelect= 0;
+ // eventType=EVENT_TYPE(x87_SIMD_moves_uop);
+ description=_T("x87_SIMD_moves_uop");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_TC_misc: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(TC_misc) * eventMask;
+
+ P4Event_TC_misc()
+ {
+ eventMask = (EVENT_MASK(TC_misc) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x01;
+ // eventType=EVENT_TYPE(TC_misc);
+ description=_T("TC_misc");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_global_power_events: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(global_power_events) * eventMask;
+
+ P4Event_global_power_events()
+ {
+ eventMask = (EVENT_MASK(global_power_events) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x13;
+ cccr.CCCRSelect= 0x06;
+ // eventType=EVENT_TYPE(global_power_events);
+ description=_T("global_power_events");
+ UseCounter0();
+ }
+
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_tc_ms_xfer: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(tc_ms_xfer) * eventMask;
+
+ P4Event_tc_ms_xfer()
+ {
+ eventMask = (EVENT_MASK(tc_ms_xfer) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x00;
+ // eventType=EVENT_TYPE(tc_ms_xfer);
+ description=_T("tc_ms_xfer");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_uop_queue_writes: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(uop_queue_writes) * eventMask;
+
+ P4Event_uop_queue_writes()
+ {
+ eventMask = (EVENT_MASK(uop_queue_writes) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x09;
+ cccr.CCCRSelect= 0x00;
+ // eventType=EVENT_TYPE(uop_queue_writes);
+ description=_T("uop_queue_writes");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_retired_mispred_branch_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_type) * eventMask;
+
+ P4Event_retired_mispred_branch_type()
+ {
+ eventMask = (EVENT_MASK(branch_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(branch_type);
+ description=_T("retired_mispred_branch_type");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_retired_branch_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_type) * eventMask;
+
+ P4Event_retired_branch_type()
+ {
+ eventMask = (EVENT_MASK(branch_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(branch_type);
+ description=_T("retired_branch_type");
+ UseCounter4();
+ }
+
+ void UseCounter4()
+ {
+ SetCounter(4);;
+ }
+ void UseCounter5()
+ {
+ SetCounter(5);
+ }
+ void UseCounter6()
+ {
+ SetCounter(6);
+ }
+ void UseCounter7()
+ {
+ SetCounter(7);
+ }
+};
+class P4Event_resource_stall: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(resource_stall) * eventMask;
+
+ P4Event_resource_stall()
+ {
+ eventMask = (EVENT_MASK(resource_stall) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(resource_stall);
+ description=_T("resource_stall");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+
+};
+class P4Event_WC_Buffer: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(WC_Buffer) * eventMask;
+
+ P4Event_WC_Buffer()
+ {
+ eventMask = (EVENT_MASK(WC_Buffer) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x05;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(WC_Buffer);
+ description=_T("WC_Buffer");
+ UseCounter8();
+ }
+ void UseCounter8()
+ {
+ SetCounter(8);
+ }
+ void UseCounter9()
+ {
+ SetCounter(9);
+ }
+ void UseCounter10()
+ {
+ SetCounter(10);
+ }
+ void UseCounter11()
+ {
+ SetCounter(11);
+ }
+
+};
+class P4Event_b2b_cycles: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(b2b_cycles) * eventMask;
+
+ P4Event_b2b_cycles()
+ {
+ eventMask = (EVENT_MASK(b2b_cycles) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x16;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(b2b_cycles);
+ description=_T("b2b_cycles");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_bnr: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(bnr) * eventMask;
+
+ P4Event_bnr()
+ {
+ eventMask = (EVENT_MASK(bnr) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(bnr);
+ description=_T("bnr");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_snoop: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(snoop) * eventMask;
+
+ P4Event_snoop()
+ {
+ eventMask = (EVENT_MASK(snoop) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(snoop);
+ description=_T("snoop");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_response: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(response) * eventMask;
+
+ P4Event_response()
+ {
+ eventMask = (EVENT_MASK(response) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x04;
+ cccr.CCCRSelect= 0x03;
+ // eventType=EVENT_TYPE(response);
+ description=_T("response");
+ UseCounter0();
+ }
+ void UseCounter0()
+ {
+ SetCounter(0);
+ }
+ void UseCounter1()
+ {
+ SetCounter(1);
+ }
+ void UseCounter2()
+ {
+ SetCounter(2);
+ }
+ void UseCounter3()
+ {
+ SetCounter(3);
+ }
+};
+class P4Event_front_end_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_front_end_event()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x08;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("front_end_event");
+ UseCounter12();
+ }
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_execution_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(execution_event) * eventMask;
+
+ P4Event_execution_event()
+ {
+ eventMask = (EVENT_MASK(execution_event) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x0C;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(execution_event);
+ description=_T("execution_event");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_replay_event: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_replay_event()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x09;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("replay_event");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_instr_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(instr_retired) * eventMask;
+
+ P4Event_instr_retired()
+ {
+ eventMask = (EVENT_MASK(instr_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(instr_retired);
+ description=_T("instr_retired");
+ UseCounter12();
+ }
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_uops_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(nbogus_bogus) * eventMask;
+
+ P4Event_uops_retired()
+ {
+ eventMask = (EVENT_MASK(nbogus_bogus) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x01;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(nbogus_bogus);
+ description=_T("uops_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_uop_type: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(uop_type) * eventMask;
+
+ P4Event_uop_type()
+ {
+ eventMask = (EVENT_MASK(uop_type) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x02;
+ // eventType=EVENT_TYPE(uop_type);
+ description=_T("uop_type");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_branch_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(branch_retired) * eventMask;
+
+ P4Event_branch_retired()
+ {
+ eventMask = (EVENT_MASK(branch_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x06;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(branch_retired);
+ description=_T("branch_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_mispred_branch_retired: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(mispred_branch_retired) * eventMask;
+
+ P4Event_mispred_branch_retired()
+ {
+ eventMask = (EVENT_MASK(mispred_branch_retired) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x04;
+ // eventType=EVENT_TYPE(mispred_branch_retired);
+ description=_T("mispred_branch_retired");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_x87_assist: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(x87_assist) * eventMask;
+
+ P4Event_x87_assist()
+ {
+ eventMask = (EVENT_MASK(x87_assist) *)&m_eventMask;
+
+ escr.ESCREventSelect= 0x03;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(x87_assist);
+ description=_T("x87_assist");
+ UseCounter12();
+ }
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+};
+class P4Event_machine_clear: public P4BaseEvent
+
+{
+public:
+ EVENT_MASK(machine_clear) * eventMask;
+
+ P4Event_machine_clear()
+ {
+ eventMask = (EVENT_MASK(machine_clear) *)&m_eventMask;
+ escr.ESCREventSelect= 0x02;
+ cccr.CCCRSelect= 0x05;
+ // eventType=EVENT_TYPE(machine_clear);
+ description=_T("machine_clear");
+ UseCounter12();
+ }
+
+
+
+ void UseCounter12()
+ {
+ SetCounter(12);
+ }
+ void UseCounter13()
+ {
+ SetCounter(13);
+
+ }
+
+ void UseCounter14()
+ {
+ SetCounter(14);
+ }
+ void UseCounter15()
+ {
+ SetCounter(15);
+
+ }
+
+ void UseCounter16()
+ {
+ SetCounter(16);
+ }
+ void UseCounter17()
+ {
+ SetCounter(17);
+
+ }
+
+};
+
+#endif // EVENTMODES_H
diff --git a/external/vpc/public/tier0/fasttimer.h b/external/vpc/public/tier0/fasttimer.h
new file mode 100644
index 0000000..a820a60
--- /dev/null
+++ b/external/vpc/public/tier0/fasttimer.h
@@ -0,0 +1,625 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef FASTTIMER_H
+#define FASTTIMER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <assert.h>
+#include "tier0/platform.h"
+#ifdef _PS3
+#include "sys/sys_time.h"
+#else
+inline uint64 sys_time_get_timebase_frequency()
+{
+ DebuggerBreak(); // Error("sys_time_get_timebase_frequency called on non-PS3 platform.");
+ return 1; // this function should never ever be called.
+}
+#endif
+
+PLATFORM_INTERFACE uint64 g_ClockSpeed;
+PLATFORM_INTERFACE unsigned long g_dwClockSpeed;
+
+PLATFORM_INTERFACE double g_ClockSpeedMicrosecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedMillisecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedSecondsMultiplier;
+
+#ifdef COMPILER_MSVC64
+extern "C"
+{
+ unsigned __int64 __rdtsc();
+}
+
+#pragma intrinsic(__rdtsc)
+#endif
+
+class CCycleCount
+{
+ friend class CFastTimer;
+
+public:
+ CCycleCount();
+ CCycleCount( uint64 cycles );
+
+ void Sample(); // Sample the clock. This takes about 34 clocks to execute (or 26,000 calls per millisecond on a P900).
+
+ void Init(); // Set to zero.
+ void Init( float initTimeMsec );
+ void Init( double initTimeMsec ) { Init( (float)initTimeMsec ); }
+ void Init( uint64 cycles );
+ bool IsLessThan( CCycleCount const &other ) const; // Compare two counts.
+
+ // Convert to other time representations. These functions are slow, so it's preferable to call them
+ // during display rather than inside a timing block.
+ unsigned long GetCycles() const;
+ uint64 GetLongCycles() const;
+
+ unsigned long GetMicroseconds() const;
+ uint64 GetUlMicroseconds() const;
+ double GetMicrosecondsF() const;
+ void SetMicroseconds( unsigned long nMicroseconds );
+
+ unsigned long GetMilliseconds() const;
+ double GetMillisecondsF() const;
+
+ double GetSeconds() const;
+
+ CCycleCount& operator+=( CCycleCount const &other );
+
+ // dest = rSrc1 + rSrc2
+ static void Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together.
+
+ // dest = rSrc1 - rSrc2
+ static void Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest ); // Add two samples together.
+
+ static uint64 GetTimestamp();
+
+ uint64 m_Int64;
+};
+
+class CClockSpeedInit
+{
+public:
+ CClockSpeedInit()
+ {
+ Init();
+ }
+
+ static void Init()
+ {
+ const CPUInformation& pi = GetCPUInformation();
+
+ if ( IsX360() )
+ {
+ // cycle counter runs as doc'd at 1/64 Xbox 3.2GHz clock speed, thus 50 Mhz
+ g_ClockSpeed = pi.m_Speed / 64L;
+ }
+ else if ( IsPS3() )
+ {
+ g_ClockSpeed = sys_time_get_timebase_frequency(); // CPU clock rate is totally unrelated to time base register frequency on PS3
+ }
+ else
+ {
+ g_ClockSpeed = pi.m_Speed;
+ }
+ g_dwClockSpeed = (unsigned long)g_ClockSpeed;
+
+ g_ClockSpeedMicrosecondsMultiplier = 1000000.0 / (double)g_ClockSpeed;
+ g_ClockSpeedMillisecondsMultiplier = 1000.0 / (double)g_ClockSpeed;
+ g_ClockSpeedSecondsMultiplier = 1.0f / (double)g_ClockSpeed;
+ }
+};
+
+class CFastTimer
+{
+public:
+ // These functions are fast to call and should be called from your sampling code.
+ void Start();
+ void End();
+
+ const CCycleCount & GetDuration() const; // Get the elapsed time between Start and End calls.
+ CCycleCount GetDurationInProgress() const; // Call without ending. Not that cheap.
+
+ // Return number of cycles per second on this processor.
+ static inline unsigned long GetClockSpeed();
+
+private:
+ CCycleCount m_Duration;
+#ifdef DEBUG_FASTTIMER
+ bool m_bRunning; // Are we currently running?
+#endif
+};
+
+
+// This is a helper class that times whatever block of code it's in
+class CTimeScope
+{
+public:
+ CTimeScope( CFastTimer *pTimer );
+ ~CTimeScope();
+
+private:
+ CFastTimer *m_pTimer;
+};
+
+inline CTimeScope::CTimeScope( CFastTimer *pTotal )
+{
+ m_pTimer = pTotal;
+ m_pTimer->Start();
+}
+
+inline CTimeScope::~CTimeScope()
+{
+ m_pTimer->End();
+}
+
+// This is a helper class that times whatever block of code it's in and
+// adds the total (int microseconds) to a global counter.
+class CTimeAdder
+{
+public:
+ CTimeAdder( CCycleCount *pTotal );
+ ~CTimeAdder();
+
+ void End();
+
+private:
+ CCycleCount *m_pTotal;
+ CFastTimer m_Timer;
+};
+
+inline CTimeAdder::CTimeAdder( CCycleCount *pTotal )
+{
+ m_pTotal = pTotal;
+ m_Timer.Start();
+}
+
+inline CTimeAdder::~CTimeAdder()
+{
+ End();
+}
+
+inline void CTimeAdder::End()
+{
+ if( m_pTotal )
+ {
+ m_Timer.End();
+ *m_pTotal += m_Timer.GetDuration();
+ m_pTotal = 0;
+ }
+}
+
+
+
+// -------------------------------------------------------------------------- //
+// Simple tool to support timing a block of code, and reporting the results on
+// program exit or at each iteration
+//
+// Macros used because dbg.h uses this header, thus Msg() is unavailable
+// -------------------------------------------------------------------------- //
+
+#define PROFILE_SCOPE(name) \
+ class C##name##ACC : public CAverageCycleCounter \
+ { \
+ public: \
+ ~C##name##ACC() \
+ { \
+ Msg("%-48s: %6.3f avg (%8.1f total, %7.3f peak, %5d iters)\n", \
+ #name, \
+ GetAverageMilliseconds(), \
+ GetTotalMilliseconds(), \
+ GetPeakMilliseconds(), \
+ GetIters() ); \
+ } \
+ }; \
+ static C##name##ACC name##_ACC; \
+ CAverageTimeMarker name##_ATM( &name##_ACC )
+
+#define TIME_SCOPE(name) \
+ class CTimeScopeMsg_##name \
+ { \
+ public: \
+ CTimeScopeMsg_##name() { m_Timer.Start(); } \
+ ~CTimeScopeMsg_##name() \
+ { \
+ m_Timer.End(); \
+ Msg( #name "time: %.4fms\n", m_Timer.GetDuration().GetMillisecondsF() ); \
+ } \
+ private: \
+ CFastTimer m_Timer; \
+ } name##_TSM;
+
+
+// -------------------------------------------------------------------------- //
+
+class CAverageCycleCounter
+{
+public:
+ CAverageCycleCounter();
+
+ void Init();
+ void MarkIter( const CCycleCount &duration );
+
+ unsigned GetIters() const;
+
+ double GetAverageMilliseconds() const;
+ double GetTotalMilliseconds() const;
+ double GetPeakMilliseconds() const;
+
+private:
+ unsigned m_nIters;
+ CCycleCount m_Total;
+ CCycleCount m_Peak;
+ bool m_fReport;
+ const tchar *m_pszName;
+};
+
+// -------------------------------------------------------------------------- //
+
+class CAverageTimeMarker
+{
+public:
+ CAverageTimeMarker( CAverageCycleCounter *pCounter );
+ ~CAverageTimeMarker();
+
+private:
+ CAverageCycleCounter *m_pCounter;
+ CFastTimer m_Timer;
+};
+
+
+// -------------------------------------------------------------------------- //
+// CCycleCount inlines.
+// -------------------------------------------------------------------------- //
+
+inline CCycleCount::CCycleCount()
+{
+ Init( (uint64)0 );
+}
+
+inline CCycleCount::CCycleCount( uint64 cycles )
+{
+ Init( cycles );
+}
+
+inline void CCycleCount::Init()
+{
+ Init( (uint64)0 );
+}
+
+inline void CCycleCount::Init( float initTimeMsec )
+{
+ if ( g_ClockSpeedMillisecondsMultiplier > 0 )
+ Init( (uint64)(initTimeMsec / g_ClockSpeedMillisecondsMultiplier) );
+ else
+ Init( (uint64)0 );
+}
+
+inline void CCycleCount::Init( uint64 cycles )
+{
+ m_Int64 = cycles;
+}
+
+#if !COMPILER_GCC
+#pragma warning(push)
+#pragma warning(disable : 4189) // warning C4189: local variable is initialized but not referenced
+#endif
+
+inline void CCycleCount::Sample()
+{
+#ifdef COMPILER_MSVC64
+ unsigned __int64* pSample = (unsigned __int64*)&m_Int64;
+ *pSample = __rdtsc();
+ // Msg( "Sample = %I64x", pSample );
+#elif defined( _X360 )
+ // only need lower 32 bits, avoids doc'd read bug and 32 bit rollover is in 85 seconds
+ m_Int64 = (uint64)__mftb32();
+ // scale back up, needs to be viewed as 1 cycle/clock
+#elif defined( _PS3 )
+ // only need lower 32 bits, avoids doc'd read bug and 32 bit rollover is in 85 seconds
+ m_Int64 = (uint64)__mftb();
+ // scale back up, needs to be viewed as 1 cycle/clock
+#elif defined( __GNUC__ )
+ union
+ {
+ unsigned long* pSample;
+ uint64 * pInt64;
+ } tmp;
+ tmp.pInt64 = &m_Int64;
+ __asm__ __volatile__ (
+ "rdtsc\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movl %%edx, 4(%0)\n\t"
+ : /* no output regs */
+ : "D" (tmp.pSample)
+ : "%eax", "%edx" );
+#elif defined( _WIN32 )
+ unsigned long* pSample = (unsigned long *)&m_Int64;
+ __asm
+ {
+ // force the cpu to synchronize the instruction queue
+ // NJS: CPUID can really impact performance in tight loops.
+ //cpuid
+ //cpuid
+ //cpuid
+ mov ecx, pSample
+ rdtsc
+ mov [ecx], eax
+ mov [ecx+4], edx
+ }
+#elif defined( POSIX )
+ unsigned long* pSample = (unsigned long *)&m_Int64;
+ __asm__ __volatile__ (
+ "rdtsc\n\t"
+ "movl %%eax, (%0)\n\t"
+ "movl %%edx, 4(%0)\n\t"
+ : /* no output regs */
+ : "D" (pSample)
+ : "%eax", "%edx" );
+#endif
+}
+
+#if !COMPILER_GCC
+#pragma warning(pop)
+#endif
+
+inline CCycleCount& CCycleCount::operator+=( CCycleCount const &other )
+{
+ m_Int64 += other.m_Int64;
+ return *this;
+}
+
+
+inline void CCycleCount::Add( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest )
+{
+ dest.m_Int64 = rSrc1.m_Int64 + rSrc2.m_Int64;
+}
+
+inline void CCycleCount::Sub( CCycleCount const &rSrc1, CCycleCount const &rSrc2, CCycleCount &dest )
+{
+ dest.m_Int64 = rSrc1.m_Int64 - rSrc2.m_Int64;
+}
+
+inline uint64 CCycleCount::GetTimestamp()
+{
+ CCycleCount c;
+ c.Sample();
+ return c.GetLongCycles();
+}
+
+inline bool CCycleCount::IsLessThan(CCycleCount const &other) const
+{
+ return m_Int64 < other.m_Int64;
+}
+
+
+inline unsigned long CCycleCount::GetCycles() const
+{
+ return (unsigned long)m_Int64;
+}
+
+inline uint64 CCycleCount::GetLongCycles() const
+{
+ return m_Int64;
+}
+
+inline unsigned long CCycleCount::GetMicroseconds() const
+{
+ return (unsigned long)((m_Int64 * 1000000) / g_ClockSpeed);
+}
+
+inline uint64 CCycleCount::GetUlMicroseconds() const
+{
+ return ((m_Int64 * 1000000) / g_ClockSpeed);
+}
+
+
+inline double CCycleCount::GetMicrosecondsF() const
+{
+ return (double)( m_Int64 * g_ClockSpeedMicrosecondsMultiplier );
+}
+
+
+inline void CCycleCount::SetMicroseconds( unsigned long nMicroseconds )
+{
+ m_Int64 = ((uint64)nMicroseconds * g_ClockSpeed) / 1000000;
+}
+
+
+inline unsigned long CCycleCount::GetMilliseconds() const
+{
+ return (unsigned long)((m_Int64 * 1000) / g_ClockSpeed);
+}
+
+
+inline double CCycleCount::GetMillisecondsF() const
+{
+ return (double)( m_Int64 * g_ClockSpeedMillisecondsMultiplier );
+}
+
+
+inline double CCycleCount::GetSeconds() const
+{
+ return (double)( m_Int64 * g_ClockSpeedSecondsMultiplier );
+}
+
+
+// -------------------------------------------------------------------------- //
+// CFastTimer inlines.
+// -------------------------------------------------------------------------- //
+inline void CFastTimer::Start()
+{
+ m_Duration.Sample();
+#ifdef DEBUG_FASTTIMER
+ m_bRunning = true;
+#endif
+}
+
+
+inline void CFastTimer::End()
+{
+ CCycleCount cnt;
+ cnt.Sample();
+ if ( IsX360() )
+ {
+ // have to handle rollover, hires timer is only accurate to 32 bits
+ // more than one overflow should not have occurred, otherwise caller should use a slower timer
+ if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 )
+ {
+ // rollover occurred
+ cnt.m_Int64 += 0x100000000LL;
+ }
+ }
+
+ m_Duration.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64;
+
+#ifdef DEBUG_FASTTIMER
+ m_bRunning = false;
+#endif
+}
+
+inline CCycleCount CFastTimer::GetDurationInProgress() const
+{
+ CCycleCount cnt;
+ cnt.Sample();
+ if ( IsX360() )
+ {
+ // have to handle rollover, hires timer is only accurate to 32 bits
+ // more than one overflow should not have occurred, otherwise caller should use a slower timer
+ if ( (uint64)cnt.m_Int64 <= (uint64)m_Duration.m_Int64 )
+ {
+ // rollover occurred
+ cnt.m_Int64 += 0x100000000LL;
+ }
+ }
+
+ CCycleCount result;
+ result.m_Int64 = cnt.m_Int64 - m_Duration.m_Int64;
+
+ return result;
+}
+
+
+inline unsigned long CFastTimer::GetClockSpeed()
+{
+ return g_dwClockSpeed;
+}
+
+
+inline CCycleCount const& CFastTimer::GetDuration() const
+{
+#ifdef DEBUG_FASTTIMER
+ assert( !m_bRunning );
+#endif
+ return m_Duration;
+}
+
+
+// -------------------------------------------------------------------------- //
+// CAverageCycleCounter inlines
+
+inline CAverageCycleCounter::CAverageCycleCounter()
+ : m_nIters( 0 )
+{
+}
+
+inline void CAverageCycleCounter::Init()
+{
+ m_Total.Init();
+ m_Peak.Init();
+ m_nIters = 0;
+}
+
+inline void CAverageCycleCounter::MarkIter( const CCycleCount &duration )
+{
+ ++m_nIters;
+ m_Total += duration;
+ if ( m_Peak.IsLessThan( duration ) )
+ m_Peak = duration;
+}
+
+inline unsigned CAverageCycleCounter::GetIters() const
+{
+ return m_nIters;
+}
+
+inline double CAverageCycleCounter::GetAverageMilliseconds() const
+{
+ if ( m_nIters )
+ return (m_Total.GetMillisecondsF() / (double)m_nIters);
+ else
+ return 0;
+}
+
+inline double CAverageCycleCounter::GetTotalMilliseconds() const
+{
+ return m_Total.GetMillisecondsF();
+}
+
+inline double CAverageCycleCounter::GetPeakMilliseconds() const
+{
+ return m_Peak.GetMillisecondsF();
+}
+
+// -------------------------------------------------------------------------- //
+
+inline CAverageTimeMarker::CAverageTimeMarker( CAverageCycleCounter *pCounter )
+{
+ m_pCounter = pCounter;
+ m_Timer.Start();
+}
+
+inline CAverageTimeMarker::~CAverageTimeMarker()
+{
+ m_Timer.End();
+ m_pCounter->MarkIter( m_Timer.GetDuration() );
+}
+
+
+// CLimitTimer
+// Use this to time whether a desired interval of time has passed. It's extremely fast
+// to check while running.
+class CLimitTimer
+{
+public:
+ void SetLimit( uint64 m_cMicroSecDuration );
+ bool BLimitReached( void );
+
+private:
+ uint64 m_lCycleLimit;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Initializes the limit timer with a period of time to measure.
+// Input : cMicroSecDuration - How long a time period to measure
+//-----------------------------------------------------------------------------
+inline void CLimitTimer::SetLimit( uint64 m_cMicroSecDuration )
+{
+ uint64 dlCycles = ( ( uint64 ) m_cMicroSecDuration * ( uint64 ) g_dwClockSpeed ) / ( uint64 ) 1000000L;
+ CCycleCount cycleCount;
+ cycleCount.Sample( );
+ m_lCycleLimit = cycleCount.GetLongCycles( ) + dlCycles;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Determines whether our specified time period has passed
+// Output: true if at least the specified time period has passed
+//-----------------------------------------------------------------------------
+inline bool CLimitTimer::BLimitReached( )
+{
+ CCycleCount cycleCount;
+ cycleCount.Sample( );
+ return ( cycleCount.GetLongCycles( ) >= m_lCycleLimit );
+}
+
+
+
+#endif // FASTTIMER_H
diff --git a/external/vpc/public/tier0/ia32detect.h b/external/vpc/public/tier0/ia32detect.h
new file mode 100644
index 0000000..e4a63a7
--- /dev/null
+++ b/external/vpc/public/tier0/ia32detect.h
@@ -0,0 +1,383 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef IA32DETECT_H
+#define IA32DETECT_H
+
+#ifdef COMPILER_MSVC64
+extern "C" void __cpuid(int* CPUInfo, int InfoType);
+#pragma intrinsic (__cpuid)
+#endif
+/*
+ This section from http://iss.cs.cornell.edu/ia32.htm
+
+
+ */
+typedef unsigned bit;
+
+enum CPUVendor
+{
+ INTEL,
+ AMD,
+ UNKNOWN_VENDOR
+};
+class ia32detect
+{
+public:
+
+ enum type_t
+ {
+ type_OEM,
+ type_OverDrive,
+ type_Dual,
+ type_reserved
+ };
+
+ enum brand_t
+ {
+ brand_na,
+ brand_Celeron,
+ brand_PentiumIII,
+ brand_PentiumIIIXeon,
+ brand_reserved1,
+ brand_reserved2,
+ brand_PentiumIIIMobile,
+ brand_reserved3,
+ brand_Pentium4,
+ brand_invalid
+ };
+
+# pragma pack(push, 1)
+
+ struct version_t
+ {
+ bit Stepping : 4;
+ bit Model : 4;
+ bit Family : 4;
+ bit Type : 2;
+ bit Reserved1 : 2;
+ bit XModel : 4;
+ bit XFamily : 8;
+ bit Reserved2 : 4;
+ };
+
+ struct misc_t
+ {
+ byte Brand;
+ byte CLFLUSH;
+ byte Reserved;
+ byte APICId;
+ };
+
+ struct feature_t
+ {
+ bit FPU : 1; // Floating Point Unit On-Chip
+ bit VME : 1; // Virtual 8086 Mode Enhancements
+ bit DE : 1; // Debugging Extensions
+ bit PSE : 1; // Page Size Extensions
+ bit TSC : 1; // Time Stamp Counter
+ bit MSR : 1; // Model Specific Registers
+ bit PAE : 1; // Physical Address Extension
+ bit MCE : 1; // Machine Check Exception
+ bit CX8 : 1; // CMPXCHG8 Instruction
+ bit APIC : 1; // APIC On-Chip
+ bit Reserved1 : 1;
+ bit SEP : 1; // SYSENTER and SYSEXIT instructions
+ bit MTRR : 1; // Memory Type Range Registers
+ bit PGE : 1; // PTE Global Bit
+ bit MCA : 1; // Machine Check Architecture
+ bit CMOV : 1; // Conditional Move Instructions
+ bit PAT : 1; // Page Attribute Table
+ bit PSE36 : 1; // 32-bit Page Size Extension
+ bit PSN : 1; // Processor Serial Number
+ bit CLFSH : 1; // CLFLUSH Instruction
+ bit Reserved2 : 1;
+ bit DS : 1; // Debug Store
+ bit ACPI : 1; // Thermal Monitor and Software Controlled Clock Facilities
+ bit MMX : 1; // Intel MMX Technology
+ bit FXSR : 1; // FXSAVE and FXRSTOR Instructions
+ bit SSE : 1; // Intel SSE Technology
+ bit SSE2 : 1; // Intel SSE2 Technology
+ bit SS : 1; // Self Snoop
+ bit HTT : 1; // Hyper Threading
+ bit TM : 1; // Thermal Monitor
+ bit Reserved3 : 1;
+ bit PBE : 1; // Pending Brk. EN.
+ };
+
+# pragma pack(pop)
+
+ tstring vendor_name;
+ CPUVendor vendor;
+ tstring brand;
+ version_t version;
+ misc_t misc;
+ feature_t feature;
+ byte *cache;
+
+ ia32detect ()
+ {
+
+ cache = 0;
+ uint32 m = init0();
+
+ uint32 *d = new uint32[m * 4];
+
+ for (uint32 i = 1; i <= m; i++)
+ {
+
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i-1) * 4), i);
+
+#else
+ uint32 *t = d + (i - 1) * 4;
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+
+ cpuid;
+
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 1)
+ init1(d);
+
+ if (m >= 2)
+ init2(d[4] & 0xFF);
+
+ delete [] d;
+
+ init0x80000000();
+
+
+ //-----------------------------------------------------------------------
+ // Get the vendor of the processor
+ //-----------------------------------------------------------------------
+ if (_tcscmp(vendor_name.c_str(), _T("GenuineIntel")) == 0)
+ {
+ vendor = INTEL;
+
+ }
+ else if (_tcscmp(vendor_name.c_str(), _T("AuthenticAMD")) == 0)
+ {
+ vendor = AMD;
+
+ }
+ else
+ {
+ vendor = UNKNOWN_VENDOR;
+ }
+ }
+
+ const tstring version_text () const
+ {
+ tchar b[128];
+
+ _stprintf(b, _T("%d.%d.%d %s XVersion(%d.%d)"),
+ version.Family, version.Model, version.Stepping, type_text(), version.XFamily, version.XModel);
+
+ return tstring(b);
+ }
+
+protected:
+
+ const tchar * type_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("Intel OEM Processor"),
+ _T("Intel OverDrive(R) Processor"),
+ _T("Intel Dual Processor"),
+ _T("reserved")
+ };
+
+ return text[version.Type];
+ }
+
+ const tstring brand_text () const
+ {
+ static const tchar *text[] =
+ {
+ _T("n/a"),
+ _T("Celeron"),
+ _T("Pentium III"),
+ _T("Pentium III Xeon"),
+ _T("reserved (4)"),
+ _T("reserved (5)"),
+ _T("Pentium III Mobile"),
+ _T("reserved (7)"),
+ _T("Pentium 4")
+ };
+
+ if (misc.Brand < brand_invalid)
+ return tstring(text[misc.Brand]);
+ else
+ {
+ tchar b[32];
+
+ _stprintf(b, _T("Brand %d (Update)"), misc.Brand);
+
+ return tstring(b);
+ }
+ }
+
+private:
+
+ uint32 init0 ()
+ {
+ uint32 m;
+
+#ifdef COMPILER_MSVC64
+ int data[4];
+ tchar * s1;
+
+ s1 = (tchar *) &data[1];
+ s1[12] = '\0';
+ __cpuid(data, 0);
+ m = data[0];
+ vendor_name = s1;
+#else
+ tchar s1[13];
+
+ s1[12] = '\0';
+ __asm
+ {
+ xor eax, eax;
+ cpuid;
+ mov m, eax;
+ mov dword ptr s1 + 0, ebx;
+ mov dword ptr s1 + 4, edx;
+ mov dword ptr s1 + 8, ecx;
+ }
+ vendor_name = s1;
+#endif
+ return m;
+ }
+
+ void init1 (uint32 *d)
+ {
+ version = *(version_t *)&d[0];
+ misc = *(misc_t *)&d[1];
+ feature = *(feature_t *)&d[3];
+ }
+
+ void process2 (uint32 d, bool c[])
+ {
+ if ((d & 0x80000000) == 0)
+ for (int i = 0; i < 32; i += 8)
+ c[(d >> i) & 0xFF] = true;
+ }
+
+ void init2 (byte count)
+ {
+ uint32 d[4];
+ bool c[256];
+
+ for (int ci1 = 0; ci1 < 256; ci1++)
+ c[ci1] = false;
+
+ for (int i = 0; i < count; i++)
+ {
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) d, 2);
+#else
+ __asm
+ {
+ mov eax, 2;
+ lea esi, d;
+ cpuid;
+ mov [esi + 0x0], eax;
+ mov [esi + 0x4], ebx;
+ mov [esi + 0x8], ecx;
+ mov [esi + 0xC], edx;
+ }
+#endif
+
+ if (i == 0)
+ d[0] &= 0xFFFFFF00;
+
+ process2(d[0], c);
+ process2(d[1], c);
+ process2(d[2], c);
+ process2(d[3], c);
+ }
+
+ int m = 0;
+
+ for (int ci2 = 0; ci2 < 256; ci2++)
+ if (c[ci2])
+ m++;
+
+ cache = new byte[m];
+
+ m = 0;
+
+ for (int ci3 = 1; ci3 < 256; ci3++)
+ if (c[ci3])
+ cache[m++] = ci3;
+
+ cache[m] = 0;
+ }
+
+ void init0x80000000 ()
+ {
+ uint32 m;
+
+#ifdef COMPILER_MSVC64
+ int data[4];
+ __cpuid(data, 0x80000000);
+ m = data[0];
+#else
+ __asm
+ {
+ mov eax, 0x80000000;
+ cpuid;
+ mov m, eax
+ }
+#endif
+
+ if ((m & 0x80000000) != 0)
+ {
+ uint32 *d = new uint32[(m - 0x80000000) * 4];
+
+ for (uint32 i = 0x80000001; i <= m; i++)
+ {
+ uint32 *t = d + (i - 0x80000001) * 4;
+
+#ifdef COMPILER_MSVC64
+ __cpuid((int *) (d + (i - 0x80000001) * 4), i);
+#else
+ __asm
+ {
+ mov eax, i;
+ mov esi, t;
+ cpuid;
+ mov dword ptr [esi + 0x0], eax;
+ mov dword ptr [esi + 0x4], ebx;
+ mov dword ptr [esi + 0x8], ecx;
+ mov dword ptr [esi + 0xC], edx;
+ }
+#endif
+ }
+
+ if (m >= 0x80000002)
+ brand = (tchar *)(d + 4);
+
+ // note the assignment to brand above does a copy, we need to delete
+ delete[] d;
+ }
+ }
+};
+
+#endif // IA32DETECT_H
diff --git a/external/vpc/public/tier0/icommandline.h b/external/vpc/public/tier0/icommandline.h
new file mode 100644
index 0000000..d56d5a3
--- /dev/null
+++ b/external/vpc/public/tier0/icommandline.h
@@ -0,0 +1,65 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+//===========================================================================//
+
+#ifndef TIER0_ICOMMANDLINE_H
+#define TIER0_ICOMMANDLINE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Interface to engine command line
+//-----------------------------------------------------------------------------
+abstract_class ICommandLine
+{
+public:
+ virtual void CreateCmdLine( const char *commandline ) = 0;
+ virtual void CreateCmdLine( int argc, char **argv ) = 0;
+ virtual const char *GetCmdLine( void ) const = 0;
+
+ // Check whether a particular parameter exists
+ virtual const char *CheckParm( const char *psz, const char **ppszValue = 0 ) const = 0;
+ virtual void RemoveParm( const char *parm ) = 0;
+ virtual void AppendParm( const char *pszParm, const char *pszValues ) = 0;
+
+ // Returns the argument after the one specified, or the default if not found
+ virtual const char *ParmValue( const char *psz, const char *pDefaultVal = 0 ) const = 0;
+ virtual int ParmValue( const char *psz, int nDefaultVal ) const = 0;
+ virtual float ParmValue( const char *psz, float flDefaultVal ) const = 0;
+
+ // Gets at particular parameters
+ virtual int ParmCount() const = 0;
+ virtual int FindParm( const char *psz ) const = 0; // Returns 0 if not found.
+ virtual const char* GetParm( int nIndex ) const = 0;
+
+ // copies the string passwed
+ virtual void SetParm( int nIndex, char const *pNewParm ) =0;
+};
+
+//-----------------------------------------------------------------------------
+// Gets a singleton to the commandline interface
+// NOTE: The #define trickery here is necessary for backwards compat:
+// this interface used to lie in the vstdlib library.
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE ICommandLine *CommandLine();
+
+
+//-----------------------------------------------------------------------------
+// Process related functions
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE const tchar *Plat_GetCommandLine();
+#ifndef _WIN32
+// helper function for OS's that don't have a ::GetCommandLine() call
+PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine );
+#endif
+PLATFORM_INTERFACE const char *Plat_GetCommandLineA();
+
+
+#endif // TIER0_ICOMMANDLINE_H
+
diff --git a/external/vpc/public/tier0/ioctlcodes.h b/external/vpc/public/tier0/ioctlcodes.h
new file mode 100644
index 0000000..7fc8efb
--- /dev/null
+++ b/external/vpc/public/tier0/ioctlcodes.h
@@ -0,0 +1,29 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef IOCTLCODES_H
+#define IOCTLCODES_H
+#pragma once
+
+// Define the IOCTL codes we will use. The IOCTL code contains a command
+// identifier, plus other information about the device, the type of access
+// with which the file must have been opened, and the type of buffering.
+
+// Device type -- in the "User Defined" range."
+#define DEVICE_FILE_TYPE 40000
+
+
+// The IOCTL function codes from 0x800 to 0xFFF are for customer use.
+
+#define IOCTL_WRITE_MSR \
+ CTL_CODE( DEVICE_FILE_TYPE, 0x900, METHOD_BUFFERED, FILE_READ_ACCESS )
+
+#define IOCTL_READ_MSR \
+ CTL_CODE( DEVICE_FILE_TYPE, 0x901, METHOD_BUFFERED, FILE_READ_ACCESS )
+
+
+#endif IOCTLCODES_H
diff --git a/external/vpc/public/tier0/k8performancecounters.h b/external/vpc/public/tier0/k8performancecounters.h
new file mode 100644
index 0000000..d405a8d
--- /dev/null
+++ b/external/vpc/public/tier0/k8performancecounters.h
@@ -0,0 +1,2040 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef K8PERFORMANCECOUNTERS_H
+#define K8PERFORMANCECOUNTERS_H
+
+/*
+ * AMD K8 events.
+ *
+ */
+
+#ifdef COMPILER_MSVC64
+extern "C"
+{
+ unsigned __int64 __readpmc(unsigned long);
+}
+
+#pragma intrinsic(__readpmc)
+#endif
+
+
+typedef union EVENT_MASK(NULL_MASK)
+{
+ // no tests defined
+ uint16 flat;
+} EVENT_MASK(NULL_MASK);
+
+
+#define MSR_K8_EVNTSEL0 0xC0010000 /* .. 0xC0010003 */
+#define MSR_K8_PERFCTR0 0xC0010004 /* .. 0xC0010007 */
+
+# pragma pack(push, 1)
+
+
+
+// access to these bits is through the methods
+typedef union PerfEvtSel
+{
+ struct
+ {
+ uint64 EventMask : 8;
+
+ uint64 UnitMask : 8;
+ uint64 USR : 1;
+ uint64 OS : 1;
+ uint64 Edge : 1;
+ uint64 PC : 1;
+ uint64 INTAPIC : 1;
+ uint64 Reserved21 : 1;
+ uint64 Enable : 1;
+ uint64 Complement : 1; // aka INV
+ uint64 Threshold : 8; // aka CounterMask
+ uint64 Reserver32 : 32;
+ };
+ uint64 flat;
+
+} PerfEvtSel;
+
+
+enum UnitEncode
+{
+ FP,
+ LS,
+ DC,
+ BU,
+ IC,
+ UE_Unknown,
+ FR,
+ NB
+};
+
+# pragma pack(pop)
+
+// Turn off the no return value warning in ReadCounter.
+#pragma warning( disable : 4035 )
+#define k8NUM_COUNTERS 4
+class k8BaseEvent
+{
+public:
+
+ PME * pme;
+
+ PerfEvtSel eventSelect[k8NUM_COUNTERS];
+
+ unsigned short m_eventMask;
+ int event_id;
+ tchar * name;
+ tchar revRequired;
+ int eventSelectNum;
+ UnitEncode unitEncode;
+
+
+ void SetCounter(int n)
+ {
+ if (n < 0)
+ n = 0;
+ else if (n > 3)
+ n = 3;
+ eventSelectNum = n;
+
+ }
+ k8BaseEvent()
+ {
+ pme = PME::Instance();
+
+ for(int i = 0; i< k8NUM_COUNTERS; i++)
+ {
+ eventSelect[i].flat = 0;
+
+ }
+ eventSelectNum = 0;
+
+ m_eventMask = 0;
+ event_id = 0;
+ name = 0;
+ revRequired = 'A';
+
+
+ }
+
+ void SetCaptureMode(PrivilegeCapture priv)
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+ StopCounter();
+
+ switch (priv)
+ {
+ case OS_Only:
+ select.USR = 0;
+ select.OS = 1;
+ break;
+
+ case USR_Only:
+ select.USR = 1;
+ select.OS = 0;
+ break;
+
+ case OS_and_USR:
+ select.USR = 1;
+ select.OS = 1;
+ break;
+ }
+
+
+ select.UnitMask = m_eventMask;
+ select.EventMask = event_id;
+
+
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+ pme->WriteMSR(selectPort, select.flat);
+ }
+
+
+ void SetFiltering(CompareState compareEnable,
+ CompareMethod compareMethod,
+ uint8 threshold,
+ EdgeState edgeEnable)
+ {
+
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ StopCounter();
+
+ if (compareEnable == CompareDisable)
+ select.Threshold = 0;
+ else
+ select.Threshold = threshold;
+
+ select.Complement = compareMethod;
+
+ select.Edge = edgeEnable;
+
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+ pme->WriteMSR(selectPort, select.flat);
+
+
+ }
+
+
+ void StartCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ select.Enable = 1;
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+
+ pme->WriteMSR(selectPort, select.flat);
+
+ }
+ void StopCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+ select.Enable = 0;
+ int selectPort = MSR_K8_EVNTSEL0 + eventSelectNum;
+
+ pme->WriteMSR(selectPort, select.flat);
+ }
+
+
+
+ void ClearCounter()
+ {
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ int counterPort = MSR_K8_PERFCTR0 + eventSelectNum;
+
+ pme->WriteMSR(counterPort, 0ui64 ); // clear
+ }
+
+ void WriteCounter(int64 value)
+ {
+
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ int counterPort = MSR_K8_PERFCTR0 + eventSelectNum;
+ pme->WriteMSR(counterPort, value); // clear
+ }
+
+ int64 ReadCounter()
+ {
+
+#if PME_DEBUG
+ PerfEvtSel & select = eventSelect[eventSelectNum];
+
+ if (select.USR == 0 && select.OS == 0)
+ return -1; // no area to collect, use SetCaptureMode
+
+ if (select.EventMask == 0)
+ return -2; // no event mask set
+
+ if (eventSelectNum < 0 || eventSelectNum > 3)
+ return -3; // counter not legal
+
+ // check revision
+
+#endif
+
+ // ReadMSR should work here too, but RDPMC should be faster
+ //ReadMSR(counterPort, int64);
+
+ // we need to copy this into a temp for some reason
+#ifdef COMPILER_MSVC64
+ return __readpmc((unsigned long) eventSelectNum);
+#else
+ int temp = eventSelectNum;
+ _asm
+ {
+ mov ecx, temp
+ RDPMC
+ }
+#endif
+
+ }
+
+
+};
+#pragma warning( default : 4035 )
+
+
+
+
+typedef union EVENT_MASK(k8_dispatched_fpu_ops)
+{
+ // event 0
+ struct
+ {
+ uint16 AddPipeOps:1; // Add pipe ops excluding junk ops" },
+ uint16 MulPipeOps:1; // Multiply pipe ops excluding junk ops" },,
+ uint16 StoreOps:1; // Store pipe ops excluding junk ops" },
+ uint16 AndPipeOpsJunk:1; // Add pipe junk ops" },,
+ uint16 MulPipeOpsJunk:1; // Multiply pipe junk ops" },
+ uint16 StoreOpsJunk:1; // Store pipe junk ops" } }
+ };
+ uint16 flat;
+} EVENT_MASK(k8_dispatched_fpu_ops);
+
+class k8Event_DISPATCHED_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCHED_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(k8_dispatched_fpu_ops) *)&m_eventMask;
+
+ event_id = 0x00;
+ unitEncode = FP;
+ name = _T("Dispatched FPU ops");
+ revRequired = 'B';
+ }
+ EVENT_MASK(k8_dispatched_fpu_ops) * eventMask;
+
+};
+
+//////////////////////////////////////////////////////////
+
+
+
+class k8Event_NO_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_NO_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x01;
+ unitEncode = FP;
+
+ name = _T("Cycles with no FPU ops retired");
+ revRequired = 'B';
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+//////////////////////////////////////////////////////////
+
+class k8Event_FAST_FPU_OPS : public k8BaseEvent
+{
+public:
+
+ k8Event_FAST_FPU_OPS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x02;
+ unitEncode = FP;
+
+ name = _T("Dispatched FPU ops that use the fast flag interface");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+//////////////////////////////////////////////////////////
+
+
+typedef union EVENT_MASK(k8_segment_register_load)
+{
+
+ struct
+ {
+ uint16 ES:1;
+ uint16 CS:1;
+ uint16 SS:1;
+ uint16 DS:1;
+ uint16 FS:1;
+ uint16 GS:1;
+ uint16 HS:1;
+ };
+ uint16 flat;
+} EVENT_MASK(k8_segment_register_load);
+
+
+class k8Event_SEG_REG_LOAD : public k8BaseEvent
+{
+public:
+
+ k8Event_SEG_REG_LOAD()
+ {
+ eventMask = (EVENT_MASK(k8_segment_register_load) *)&m_eventMask;
+ name = _T("Segment register load");
+ event_id = 0x20;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(k8_segment_register_load) * eventMask;
+
+};
+
+
+class k8Event_SELF_MODIFY_RESYNC : public k8BaseEvent
+{
+public:
+
+ k8Event_SELF_MODIFY_RESYNC()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural resync caused by self modifying code");
+ event_id = 0x21;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+class k8Event_LS_RESYNC_BY_SNOOP : public k8BaseEvent
+{
+public:
+
+ k8Event_LS_RESYNC_BY_SNOOP()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x22;
+ unitEncode = LS;
+
+ name = _T("Microarchitectural resync caused by snoop");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+class k8Event_LS_BUFFER_FULL : public k8BaseEvent
+{
+public:
+
+ k8Event_LS_BUFFER_FULL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("LS Buffer 2 Full");
+ event_id = 0x23;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+typedef union EVENT_MASK(k8_locked_op)
+{
+
+
+ struct
+ {
+ uint16 NumLockInstr : 1; //Number of lock instructions executed
+ uint16 NumCyclesInRequestGrant : 1; //Number of cycles spent in the lock request/grant stage
+
+ uint16 NumCyclesForLock:1;
+ /*Number of cycles a lock takes to complete once it is
+ non-speculative and is the oldest load/store operation
+ (non-speculative cycles in Ls2 entry 0)*/
+
+
+ };
+ uint16 flat;
+
+
+} EVENT_MASK(k8_locked_op);
+
+
+
+class k8Event_LOCKED_OP : public k8BaseEvent
+{
+public:
+
+ EVENT_MASK(k8_locked_op) * eventMask;
+
+ k8Event_LOCKED_OP()
+ {
+ eventMask = (EVENT_MASK(k8_locked_op) *)&m_eventMask;
+ name = _T("Locked operation");
+ event_id = 0x24;
+ unitEncode = LS;
+
+ revRequired = 'C';
+ }
+
+
+};
+
+class k8Event_OP_LATE_CANCEL : public k8BaseEvent
+{
+public:
+
+ k8Event_OP_LATE_CANCEL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural late cancel of an operation");
+ event_id = 0x25;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("OP_LATE_CANCEL");
+
+
+};
+class k8Event_CFLUSH_RETIRED : public k8BaseEvent
+{
+public:
+
+ k8Event_CFLUSH_RETIRED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired CFLUSH instructions");
+ event_id = 0x26;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CFLUSH_RETIRED");
+
+
+};
+class k8Event_CPUID_RETIRED : public k8BaseEvent
+{
+public:
+
+ k8Event_CPUID_RETIRED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired CPUID instructions");
+ event_id = 0x27;
+ unitEncode = LS;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CPUID_RETIRED");
+
+
+};
+
+typedef union EVENT_MASK( k8_cache)
+{
+
+ struct
+ {
+ uint16 Invalid:1;
+ uint16 Exclusive:1;
+ uint16 Shared:1;
+ uint16 Owner:1;
+ uint16 Modified:1;
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_cache);
+ /* 0x40-0x47: from K7 official event set */
+
+
+class k8Event_DATA_CACHE_ACCESSES : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_ACCESSES()
+ {
+
+ event_id = 0x40;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //_T("DATA_CACHE_ACCESSES"),
+ name = _T("Data cache accesses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_MISSES : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_MISSES()
+ {
+
+ event_id = 0x41;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //_T("DATA_CACHE_MISSES"),
+ name = _T("Data cache misses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_DATA_CACHE_REFILLS_FROM_L2 : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_REFILLS_FROM_L2()
+ {
+
+ event_id = 0x42;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+
+ name = _T("Data cache refills from L2");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_REFILLS_FROM_SYSTEM()
+ {
+
+ event_id = 0x43;
+ unitEncode = DC;
+
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+ //UM(k7_um_moesi),
+ //_T("DATA_CACHE_REFILLS_FROM_SYSTEM"),
+ name = _T("Data cache refills from system");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+};
+
+class k8Event_DATA_CACHE_WRITEBACKS : public k8BaseEvent
+{
+ k8Event_DATA_CACHE_WRITEBACKS()
+ {
+
+ event_id = 0x44;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+
+ //UM(k7_um_moesi),
+ //_T("DATA_CACHE_WRITEBACKS"),
+ name = _T("Data cache writebacks");
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+
+
+};
+
+class k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS : public k8BaseEvent
+{
+ k8Event_L1_DTLB_MISSES_AND_L2_DTLB_HITS()
+ {
+
+ event_id = 0x45;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("L1 DTLB misses and L2 DTLB hits");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+
+class k8Event_L1_AND_L2_DTLB_MISSES : public k8BaseEvent
+{
+ k8Event_L1_AND_L2_DTLB_MISSES()
+ {
+
+ event_id = 0x46;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("L1 and L2 DTLB misses") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+class k8Event_MISALIGNED_DATA_REFERENCES : public k8BaseEvent
+{
+ k8Event_MISALIGNED_DATA_REFERENCES()
+ {
+
+ event_id = 0x47;
+ unitEncode = DC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //NULL, _T("MISALIGNED_DATA_REFERENCES"),
+ name = _T("Misaligned data references");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+
+class k8Event_ACCESS_CANCEL_LATE : public k8BaseEvent
+{
+public:
+
+ k8Event_ACCESS_CANCEL_LATE()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural late cancel of an access");
+ event_id = 0x48;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("ACCESS_CANCEL_LATE");
+
+
+};
+class k8Event_ACCESS_CANCEL_EARLY : public k8BaseEvent
+{
+public:
+
+ k8Event_ACCESS_CANCEL_EARLY()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Microarchitectural early cancel of an access");
+ event_id = 0x49;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("ACCESS_CANCEL_EARLY");
+
+
+};
+typedef union EVENT_MASK( k8_ecc)
+{
+ struct
+ {
+ uint16 ScrubberError : 1; // Scrubber error" },
+ uint16 PiggybackScrubberErrors : 1; // Piggyback scrubber errors" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_ecc);
+
+
+class k8Event_ECC_BIT_ERR : public k8BaseEvent
+{
+public:
+
+ k8Event_ECC_BIT_ERR()
+ {
+ eventMask = (EVENT_MASK(k8_ecc) *)&m_eventMask;
+ name = _T("One bit ECC error recorded found by scrubber");
+ event_id = 0x4A;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(k8_ecc) * eventMask;
+ // name = _T("ECC_BIT_ERR");
+
+
+};
+
+// 4B
+typedef union EVENT_MASK( k8_distpatch_prefetch_instructions)
+{
+ struct
+ {
+ uint16 Load : 1;
+ uint16 Store : 1;
+ uint16 NTA : 1;
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_distpatch_prefetch_instructions);
+
+class k8Event_DISPATCHED_PRE_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCHED_PRE_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_distpatch_prefetch_instructions) *)&m_eventMask;
+ name = _T("Dispatched prefetch instructions");
+ event_id = 0x4B;
+ unitEncode = DC;
+
+ }
+ EVENT_MASK(k8_distpatch_prefetch_instructions) * eventMask;
+ // name = _T("DISPATCHED_PRE_INSTRS");
+
+ /* 0x4C: added in Revision C */
+
+};
+
+
+
+typedef union EVENT_MASK( k8_lock_accesses)
+{
+ struct
+ {
+ uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" },
+ uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_lock_accesses);
+
+
+
+class k8Event_LOCK_ACCESSES : public k8BaseEvent
+{
+public:
+
+ k8Event_LOCK_ACCESSES()
+ {
+ eventMask = (EVENT_MASK(k8_lock_accesses) *)&m_eventMask;
+ name = _T("DCACHE accesses by locks") ;
+ event_id = 0x4C;
+ unitEncode = DC;
+
+ revRequired = 'C';
+ }
+ EVENT_MASK(k8_lock_accesses) * eventMask;
+
+
+};
+
+
+class k8Event_CYCLES_PROCESSOR_IS_RUNNING : public k8BaseEvent
+{
+public:
+
+ k8Event_CYCLES_PROCESSOR_IS_RUNNING()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Cycles processor is running (not in HLT or STPCLK)");
+ event_id = 0x76;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("CYCLES_PROCESSOR_IS_RUNNING"); /* undocumented *;
+
+
+};
+
+
+typedef union EVENT_MASK( k8_internal_L2_request)
+{
+ struct
+ {
+ uint16 ICFill:1; // IC fill" },
+ uint16 DCFill:1; // DC fill" },
+ uint16 TLBReload:1; // TLB reload" },
+ uint16 TagSnoopRequest:1; // Tag snoop request" },
+ uint16 CancelledRequest:1; // Cancelled request" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_internal_L2_request);
+
+class k8Event_BU_INT_L2_REQ : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_INT_L2_REQ()
+ {
+ eventMask = (EVENT_MASK(k8_internal_L2_request) *)&m_eventMask;
+ name = _T("Internal L2 request");
+ unitEncode = BU;
+ event_id = 0x7D;
+ }
+
+ EVENT_MASK(k8_internal_L2_request) * eventMask;
+} ;
+
+ // name = _T("BU_INT_L2_REQ");
+
+
+
+// 7E
+typedef union EVENT_MASK( k8_fill_request_missed_L2)
+{
+
+ struct
+ {
+ uint16 ICFill:1; // IC fill" },
+ uint16 DCFill:1; // DC fill" },
+ uint16 TLBReload:1; // TLB reload" },
+ };
+ uint16 flat;
+
+} EVENT_MASK( k8_fill_request_missed_L2);
+
+
+class k8Event_BU_FILL_REQ : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_FILL_REQ()
+ {
+ eventMask = (EVENT_MASK(k8_fill_request_missed_L2) *)&m_eventMask;
+ name = _T("Fill request that missed in L2");
+ event_id = 0x7E;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(k8_fill_request_missed_L2) * eventMask;
+ // name = _T("BU_FILL_REQ");
+
+
+
+};
+
+
+
+
+// 7F
+typedef union EVENT_MASK( k8_fill_into_L2)
+{
+
+ struct
+ {
+ uint16 DirtyL2Victim:1; // Dirty L2 victim
+ uint16 VictimFromL2:1; // Victim from L2
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_fill_into_L2);
+
+class k8Event_BU_FILL_L2 : public k8BaseEvent
+{
+public:
+
+ k8Event_BU_FILL_L2()
+ {
+ eventMask = (EVENT_MASK(k8_fill_into_L2) *)&m_eventMask;
+ name = _T("Fill into L2");
+ event_id = 0x7F;
+ unitEncode = BU;
+
+ }
+ EVENT_MASK(k8_fill_into_L2) * eventMask;
+ // name = _T("BU_FILL_L2");
+
+
+};
+
+class k8Event_INSTRUCTION_CACHE_FETCHES : public k8BaseEvent
+{
+public:
+ k8Event_INSTRUCTION_CACHE_FETCHES()
+ {
+ event_id = 0x80;
+ unitEncode = IC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ name = _T("Instruction cache fetches");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_INSTRUCTION_CACHE_MISSES : public k8BaseEvent
+{
+public:
+ k8Event_INSTRUCTION_CACHE_MISSES()
+ {
+ event_id = 0x81;
+ unitEncode = IC;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //0xF, NULL, _T("INSTRUCTION_CACHE_MISSES"),
+ name = _T("Instruction cache misses");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_IC_REFILL_FROM_L2 : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_REFILL_FROM_L2()
+ {
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+ name = _T("Refill from L2");
+ event_id = 0x82;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+ // name = _T("IC_REFILL_FROM_L2");
+
+
+
+};
+class k8Event_IC_REFILL_FROM_SYS : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_REFILL_FROM_SYS()
+ {
+ eventMask = (EVENT_MASK(k8_cache) *)&m_eventMask;
+ name = _T("Refill from system");
+ event_id = 0x83;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(k8_cache) * eventMask;
+ // name = _T("IC_REFILL_FROM_SYS");
+
+
+
+};
+class k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS : public k8BaseEvent
+{
+public:
+ k8Event_L1_ITLB_MISSES_AND_L2_ITLB_HITS()
+ {
+
+ event_id = 0x84;
+ unitEncode = IC;
+
+ name = _T("L1 ITLB misses (and L2 ITLB hits)");
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+};
+
+class k8Event_L1_AND_L2_ITLB_MISSES : public k8BaseEvent
+{
+public:
+ k8Event_L1_AND_L2_ITLB_MISSES()
+ {
+ event_id = 0x85;
+ unitEncode = IC;
+
+ name = _T("(L1 and) L2 ITLB misses");
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+
+
+class k8Event_IC_RESYNC_BY_SNOOP : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_RESYNC_BY_SNOOP()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ event_id = 0x86;
+ unitEncode = IC;
+
+ name = _T("Microarchitectural resync caused by snoop");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_RESYNC_BY_SNOOP");
+ /* similar to 0x22; but IC unit instead of LS unit */
+
+
+
+};
+class k8Event_IC_FETCH_STALL : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_FETCH_STALL()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Instruction fetch stall");
+ event_id = 0x87;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_FETCH_STALL");
+
+
+
+};
+class k8Event_IC_STACK_HIT : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_STACK_HIT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Return stack hit");
+ event_id = 0x88;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_STACK_HIT");
+
+
+
+};
+class k8Event_IC_STACK_OVERFLOW : public k8BaseEvent
+{
+public:
+
+ k8Event_IC_STACK_OVERFLOW()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Return stack overflow");
+ event_id = 0x89;
+ unitEncode = IC;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("IC_STACK_OVERFLOW");
+
+
+
+
+};
+
+ /* 0xC0-0xC7: from K7 official event set */
+class k8Event_RETIRED_INSTRUCTIONS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_INSTRUCTIONS()
+ {
+ event_id = 0xC0;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ //0xF, NULL, _T("RETIRED_INSTRUCTIONS"),
+ name = _T("Retired instructions (includes exceptions, interrupts, resyncs)");
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_RETIRED_OPS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_OPS()
+ {
+ event_id = 0xC1;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_OPS"),
+ name = _T("Retired Ops") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_BRANCHES()
+ {
+ event_id = 0xC2;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_BRANCHES"),
+ name = _T("Retired branches (conditional, unconditional, exceptions, interrupts)") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_BRANCHES_MISPREDICTED : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_BRANCHES_MISPREDICTED()
+ {
+ event_id = 0xC3;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_BRANCHES_MISPREDICTED"),
+ name = _T("Retired branches mispredicted") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_TAKEN_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_TAKEN_BRANCHES()
+ {
+ event_id = 0xC4;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES"),
+ name = _T("Retired taken branches") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_TAKEN_BRANCHES_MISPREDICTED()
+ {
+ event_id = 0xC5;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_TAKEN_BRANCHES_MISPREDICTED"),
+ name = _T("Retired taken branches mispredicted") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_FAR_CONTROL_TRANSFERS : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_FAR_CONTROL_TRANSFERS()
+ {
+ event_id = 0xC6;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_FAR_CONTROL_TRANSFERS"),
+ name = _T("Retired far control transfers") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+class k8Event_RETIRED_RESYNC_BRANCHES : public k8BaseEvent
+{
+public:
+ k8Event_RETIRED_RESYNC_BRANCHES()
+ {
+ event_id = 0xC7;
+ unitEncode = FR;
+
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ //0xF, NULL, _T("RETIRED_RESYNC_BRANCHES"),
+ name = _T("Retired resync branches (only non-control transfer branches counted)") ;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+};
+
+class k8Event_RETIRED_NEAR_RETURNS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_NEAR_RETURNS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired near returns");
+ event_id = 0xC8;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+
+
+};
+class k8Event_RETIRED_RETURNS_MISPREDICT : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_RETURNS_MISPREDICT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired near returns mispredicted");
+ event_id = 0xC9;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("RETIRED_RETURNS_MISPREDICT");
+
+
+};
+class k8Event_RETIRED_BRANCH_MISCOMPARE : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_BRANCH_MISCOMPARE()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Retired taken branches mispredicted due to address miscompare");
+ event_id = 0xCA;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("RETIRED_BRANCH_MISCOMPARE");
+
+
+};
+
+
+ /* Revision B and later */
+
+typedef union EVENT_MASK( k8_retired_fpu_instr)
+{
+ struct
+ {
+ uint16 DirtyL2Victim:1; // x87 instructions
+ uint16 CombinedMMX_3DNow:1; // Combined MMX & 3DNow! instructions" },
+ uint16 CombinedPackedSSE_SSE2:1; // Combined packed SSE and SSE2 instructions" },
+ uint16 CombinedScalarSSE_SSE2:1; // Combined scalar SSE and SSE2 instructions" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_retired_fpu_instr);
+
+
+class k8Event_RETIRED_FPU_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_FPU_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_retired_fpu_instr) *)&m_eventMask;
+ event_id = 0xCB;
+ unitEncode = FR;
+
+ name = _T("Retired FPU instructions");
+ revRequired = 'B';
+ }
+ EVENT_MASK(k8_retired_fpu_instr) * eventMask;
+ /* Revision B and later */
+
+
+
+};
+
+// CC
+typedef union EVENT_MASK( k8_retired_fastpath_double_op_instr )
+{
+
+ struct
+ {
+ uint16 LowOpPosition0:1; // With low op in position 0" },
+ uint16 LowOpPosition1:1; // With low op in position 1" },
+ uint16 LowOpPosition2:1; // With low op in position 2" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_retired_fastpath_double_op_instr);
+
+class k8Event_RETIRED_FASTPATH_INSTRS : public k8BaseEvent
+{
+public:
+
+ k8Event_RETIRED_FASTPATH_INSTRS()
+ {
+ eventMask = (EVENT_MASK(k8_retired_fastpath_double_op_instr) *)&m_eventMask;
+ event_id = 0xCC;
+ unitEncode = FR;
+
+ name = _T("Retired fastpath double op instructions");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(k8_retired_fastpath_double_op_instr) * eventMask;
+
+
+};
+
+class k8Event_INTERRUPTS_MASKED_CYCLES : public k8BaseEvent
+{
+public:
+ k8Event_INTERRUPTS_MASKED_CYCLES()
+ {
+ event_id = 0xCD;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("INTERRUPTS_MASKED_CYCLES"),
+ name = _T("Interrupts masked cycles (IF=0)") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+class k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES : public k8BaseEvent
+{
+public:
+ k8Event_INTERRUPTS_MASKED_WHILE_PENDING_CYCLES()
+ {
+ event_id = 0xCE;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("INTERRUPTS_MASKED_WHILE_PENDING_CYCLES"),
+ name = _T("Interrupts masked while pending cycles (INTR while IF=0)") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+class k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS : public k8BaseEvent
+{
+public:
+ k8Event_NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS()
+ {
+ event_id = 0xCF;
+ unitEncode = FR;
+
+ //0xF, NULL, _T("NUMBER_OF_TAKEN_HARDWARE_INTERRUPTS"),
+ name = _T("Number of taken hardware interrupts") ;
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+
+};
+
+
+class k8Event_DECODER_EMPTY : public k8BaseEvent
+{
+public:
+
+ k8Event_DECODER_EMPTY()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Nothing to dispatch (decoder empty)");
+ event_id = 0xD0;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DECODER_EMPTY");
+
+
+};
+class k8Event_DISPATCH_STALLS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALLS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stalls (events 0xD2-0xDA combined)");
+ event_id = 0xD1;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALLS");
+
+
+
+};
+class k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_FROM_BRANCH_ABORT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall from branch abort to retire");
+ event_id = 0xD2;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_FROM_BRANCH_ABORT");
+
+
+
+};
+class k8Event_DISPATCH_STALL_SERIALIZATION : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_SERIALIZATION()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall for serialization");
+ event_id = 0xD3;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_SERIALIZATION");
+
+
+};
+class k8Event_DISPATCH_STALL_SEG_LOAD : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_SEG_LOAD()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall for segment load");
+ event_id = 0xD4;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_SEG_LOAD");
+
+
+
+};
+class k8Event_DISPATCH_STALL_REORDER_BUFFER : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_REORDER_BUFFER()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when reorder buffer is full");
+ event_id = 0xD5;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_REORDER_BUFFER");
+
+
+};
+class k8Event_DISPATCH_STALL_RESERVE_STATIONS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_RESERVE_STATIONS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when reservation stations are full");
+ event_id = 0xD6;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_RESERVE_STATIONS");
+
+
+};
+class k8Event_DISPATCH_STALL_FPU : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_FPU()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when FPU is full");
+ event_id = 0xD7;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_FPU");
+
+
+};
+class k8Event_DISPATCH_STALL_LS : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_LS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when LS is full");
+ event_id = 0xD8;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_LS");
+
+
+};
+class k8Event_DISPATCH_STALL_QUIET_WAIT : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_QUIET_WAIT()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when waiting for all to be quiet");
+ event_id = 0xD9;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_QUIET_WAIT");
+
+
+
+};
+class k8Event_DISPATCH_STALL_PENDING : public k8BaseEvent
+{
+public:
+
+ k8Event_DISPATCH_STALL_PENDING()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Dispatch stall when far control transfer or resync branch is pending");
+ event_id = 0xDA;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DISPATCH_STALL_PENDING");
+
+
+
+};
+
+
+typedef union EVENT_MASK( k8_fpu_exceptions)
+{
+
+
+
+ struct
+ {
+ uint16 x87ReclassMicrofaults:1; // x87 reclass microfaults" },
+ uint16 SSERetypeMicrofaults:1; // SSE retype microfaults" },
+ uint16 SSEReclassMicrofaults:1; // SSE reclass microfaults" },
+ uint16 SSE_x87Microtraps:1; // SSE and x87 microtraps" } }
+ };
+ uint16 flat;
+
+
+
+}EVENT_MASK( k8_fpu_exceptions);
+
+class k8Event_FPU_EXCEPTIONS : public k8BaseEvent
+{
+public:
+
+ k8Event_FPU_EXCEPTIONS()
+ {
+ eventMask = (EVENT_MASK(k8_fpu_exceptions) *)&m_eventMask;
+ event_id = 0xDB;
+ unitEncode = FR;
+
+ name = _T("FPU exceptions");
+ revRequired = 'B';
+
+ }
+ EVENT_MASK(k8_fpu_exceptions) * eventMask;
+ // name = _T("FPU_EXCEPTIONS");
+ /* Revision B and later */
+
+
+
+};
+class k8Event_DR0_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR0_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR0");
+ event_id = 0xDC;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR0_BREAKPOINTS");
+
+
+
+};
+class k8Event_DR1_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR1_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR1");
+ event_id = 0xDD;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR1_BREAKPOINTS");
+
+
+
+};
+class k8Event_DR2_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR2_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR2");
+ event_id = 0xDE;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR2_BREAKPOINTS");
+
+
+};
+class k8Event_DR3_BREAKPOINTS : public k8BaseEvent
+{
+public:
+
+ k8Event_DR3_BREAKPOINTS()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Number of breakpoints for DR3");
+ event_id = 0xDF;
+ unitEncode = FR;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DR3_BREAKPOINTS");
+
+
+};
+
+
+
+// E0
+typedef union EVENT_MASK( k8_page_access_event)
+{
+ struct
+ {
+ uint16 PageHit:1; // Page hit" },
+ uint16 PageMiss:1; // Page miss" },
+ uint16 PageConflict:1; // Page conflict" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_page_access_event);
+
+class k8Event_MEM_PAGE_ACCESS : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_PAGE_ACCESS()
+ {
+ eventMask = (EVENT_MASK(k8_page_access_event) *)&m_eventMask;
+ name = _T("Memory controller page access");
+ event_id = 0xE0;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_page_access_event) * eventMask;
+ // name = _T("MEM_PAGE_ACCESS");
+
+
+};
+class k8Event_MEM_PAGE_TBL_OVERFLOW : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_PAGE_TBL_OVERFLOW()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Memory controller page table overflow");
+ event_id = 0xE1;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("MEM_PAGE_TBL_OVERFLOW");
+
+
+};
+class k8Event_DRAM_SLOTS_MISSED : public k8BaseEvent
+{
+public:
+
+ k8Event_DRAM_SLOTS_MISSED()
+ {
+ eventMask = (EVENT_MASK(NULL_MASK) *)&m_eventMask;
+ name = _T("Memory controller DRAM command slots missed (in MemClks)");
+ event_id = 0xE2;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(NULL_MASK) * eventMask;
+ // name = _T("DRAM_SLOTS_MISSED");
+
+
+};
+
+
+// e3
+typedef union EVENT_MASK( k8_turnaround)
+{
+
+ struct
+ {
+ uint16 DIMMTurnaround:1; //DIMM turnaround" },
+ uint16 ReadToWriteTurnaround:1; //Read to write turnaround" },
+ uint16 WriteToReadTurnaround:1; //Write to read turnaround" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_turnaround);
+
+class k8Event_MEM_TURNAROUND : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_TURNAROUND()
+ {
+ eventMask = (EVENT_MASK(k8_turnaround) *)&m_eventMask;
+ name = _T("Memory controller turnaround");
+ event_id = 0xE3;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_turnaround) * eventMask;
+ // name = _T("MEM_TURNAROUND");
+
+
+};
+
+
+
+
+// E4
+typedef union EVENT_MASK( k8_bypass_counter_saturation)
+{
+ struct
+ {
+ uint16 MEM_HighPriorityBypass:1; // Memory controller high priority bypass" },
+ uint16 MEM_LowPriorityBypass:1; // Memory controller low priority bypass" },
+ uint16 DRAM_InterfaceBypass:1; // DRAM controller interface bypass" },
+ uint16 DRAM_QueueBypass:1; // DRAM controller queue bypass" } }
+ };
+ uint16 flat;
+
+}EVENT_MASK( k8_bypass_counter_saturation);
+
+class k8Event_MEM_BYPASS_SAT : public k8BaseEvent
+{
+public:
+
+ k8Event_MEM_BYPASS_SAT()
+ {
+ eventMask = (EVENT_MASK(k8_bypass_counter_saturation) *)&m_eventMask;
+ name = _T("Memory controller bypass counter saturation");
+ event_id = 0xE4;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_bypass_counter_saturation) * eventMask;
+ // name = _T("MEM_BYPASS_SAT");
+
+
+};
+
+
+
+//EB
+typedef union EVENT_MASK( k8_sized_commands)
+{
+
+ struct
+ {
+ uint16 NonPostWrSzByte:1; // NonPostWrSzByte" },
+ uint16 NonPostWrSzDword:1; // NonPostWrSzDword" },
+ uint16 PostWrSzByte:1; // PostWrSzByte" },
+ uint16 PostWrSzDword:1; // PostWrSzDword" },
+ uint16 RdSzByte:1; // RdSzByte" },
+ uint16 RdSzDword:1; // RdSzDword" },
+ uint16 RdModWr:1; // RdModWr" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_sized_commands);
+
+
+class k8Event_SIZED_COMMANDS : public k8BaseEvent
+{
+public:
+
+ k8Event_SIZED_COMMANDS()
+ {
+ eventMask = (EVENT_MASK(k8_sized_commands) *)&m_eventMask;
+ name = _T("Sized commands");
+ event_id = 0xEB;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_sized_commands) * eventMask;
+ // name = _T("SIZED_COMMANDS");
+
+
+};
+
+typedef union EVENT_MASK( k8_probe_result)
+{
+ struct
+ {
+ uint16 ProbeMiss:1; // Probe miss" },
+ uint16 ProbeHit:1; // Probe hit" },
+ uint16 ProbeHitDirtyWithoutMemoryCancel:1; // Probe hit dirty without memory cancel" },
+ uint16 ProbeHitDirtyWithMemoryCancel:1; // Probe hit dirty with memory cancel" } }
+ uint16 UpstreamDisplayRefreshReads:1; // Rev D and later
+ uint16 UpstreamNonDisplayRefreshReads:1; // Rev D and later
+ uint16 UpstreamWrites:1; // Rev D and later
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_probe_result);
+
+
+class k8Event_PROBE_RESULT : public k8BaseEvent
+{
+public:
+
+ k8Event_PROBE_RESULT()
+ {
+ eventMask = (EVENT_MASK(k8_probe_result) *)&m_eventMask;
+ name = _T("Probe result");
+ event_id = 0xEC;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_probe_result) * eventMask;
+ // name = _T("PROBE_RESULT");
+
+
+};
+
+typedef union EVENT_MASK( k8_ht)
+{
+
+ struct
+ {
+ uint16 CommandSent:1; //Command sent" },
+ uint16 DataSent:1; //Data sent" },
+ uint16 BufferReleaseSent:1; //Buffer release sent"
+ uint16 NopSent:1; //Nop sent" } }
+ };
+ uint16 flat;
+
+
+}EVENT_MASK( k8_ht);
+
+
+class k8Event_HYPERTRANSPORT_BUS0_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS0_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 0 bandwidth");
+ event_id = 0xF6;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS0_WIDTH");
+
+
+};
+class k8Event_HYPERTRANSPORT_BUS1_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS1_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 1 bandwidth");
+ event_id = 0xF7;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS1_WIDTH");
+
+
+};
+class k8Event_HYPERTRANSPORT_BUS2_WIDTH : public k8BaseEvent
+{
+public:
+
+ k8Event_HYPERTRANSPORT_BUS2_WIDTH()
+ {
+ eventMask = (EVENT_MASK(k8_ht) *)&m_eventMask;
+ name = _T("Hypertransport (tm) bus 2 bandwidth");
+ event_id = 0xF8;
+ unitEncode = NB;
+
+ }
+ EVENT_MASK(k8_ht) * eventMask;
+ // name = _T("HYPERTRANSPORT_BUS2_WIDTH");
+
+};
+
+//
+//typedef union EVENT_MASK( perfctr_event_set k8_common_event_set)
+//{
+//
+// .cpu_type = PERFCTR_X86_AMD_K8,
+// .event_prefix = _T("K8_"),
+// .include = &k7_official_event_set,
+// .nevents = ARRAY_SIZE(k8_common_events),
+// .events = k8_common_events,
+//}EVENT_MASK( perfctr_event_set k8_common_event_set);
+//
+//typedef union EVENT_MASK( perfctr_event k8_events[])
+//{
+//
+// { 0x24, 0xF, UM(NULL), _T("LOCKED_OP"), /* unit mask changed in Rev. C */
+// _T("Locked operation") },
+//}EVENT_MASK( perfctr_event k8_events[]);
+
+
+
+
+//const struct perfctr_event_set perfctr_k8_event_set)
+//{
+//
+// .cpu_type = PERFCTR_X86_AMD_K8,
+// .event_prefix = _T("K8_"),
+// .include = &k8_common_event_set,
+// .nevents = ARRAY_SIZE(k8_events),
+// .events = k8_events,
+//};
+//
+/*
+ * K8 Revision C. Starts at CPUID 0xF58 for Opteron/Athlon64FX and
+ * CPUID 0xF48 for Athlon64. (CPUID 0xF51 is Opteron Revision B3.)
+ */
+
+
+
+
+
+
+
+
+//
+//typedef union EVENT_MASK( k8_lock_accesses)
+//{
+// struct
+// {
+// uint16 DcacheAccesses:1; // Number of dcache accesses by lock instructions" },
+// uint16 DcacheMisses:1; // Number of dcache misses by lock instructions" } }
+// };
+// uint16 flat;
+//
+//}EVENT_MASK( k8_lock_accesses);
+//
+
+#endif // K8PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/l2cache.h b/external/vpc/public/tier0/l2cache.h
new file mode 100644
index 0000000..db54695
--- /dev/null
+++ b/external/vpc/public/tier0/l2cache.h
@@ -0,0 +1,47 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+#ifndef CL2CACHE_H
+#define CL2CACHE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+class P4Event_BSQ_cache_reference;
+
+class CL2Cache
+{
+public:
+
+ CL2Cache();
+ ~CL2Cache();
+
+ void Start( void );
+ void End( void );
+
+ //-------------------------------------------------------------------------
+ // GetL2CacheMisses
+ //-------------------------------------------------------------------------
+ int GetL2CacheMisses( void )
+ {
+ return m_iL2CacheMissCount;
+ }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+private:
+
+ int m_nID;
+
+ P4Event_BSQ_cache_reference *m_pL2CacheEvent;
+ int64 m_i64Start;
+ int64 m_i64End;
+ int m_iL2CacheMissCount;
+};
+
+#endif // CL2CACHE_H
+
diff --git a/external/vpc/public/tier0/logging.h b/external/vpc/public/tier0/logging.h
new file mode 100644
index 0000000..42b10c4
--- /dev/null
+++ b/external/vpc/public/tier0/logging.h
@@ -0,0 +1,767 @@
+//============ Copyright (c) Valve Corporation, All rights reserved. ============
+//
+// Logging system declarations.
+//
+// The logging system is a channel-based output mechanism which allows
+// subsystems to route their text/diagnostic output to various listeners
+//
+//===============================================================================
+
+#ifndef LOGGING_H
+#define LOGGING_H
+
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+#include "color.h"
+#include "icommandline.h"
+#include <stdio.h>
+
+// For XBX_** functions
+#if defined( _X360 )
+#include "xbox/xbox_console.h"
+#endif
+
+// Used by CColorizedLoggingListener
+#if defined( _WIN32 ) || (defined(POSIX) && !defined(_GAMECONSOLE))
+#include "tier0/win32consoleio.h"
+#endif
+
+/*
+ ---- Logging System ----
+
+ The logging system is a channel-based mechanism for all code (engine,
+ mod, tool) across all platforms to output information, warnings,
+ errors, etc.
+
+ This system supersedes the existing Msg(), Warning(), Error(), DevMsg(), ConMsg() etc. functions.
+ There are channels defined in the new system through which all old messages are routed;
+ see LOG_GENERAL, LOG_CONSOLE, LOG_DEVELOPER, etc.
+
+ To use the system, simply call one of the predefined macros:
+
+ Log_Msg( ChannelID, [Color], Message, ... )
+ Log_Warning( ChannelID, [Color], Message, ... )
+ Log_Error( ChannelID, [Color], Message, ... )
+
+ A ChannelID is typically created by defining a logging channel with the
+ log channel macros:
+
+ DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
+
+ or
+
+ BEGIN_DEFINE_LOGGING_CHANNEL( LOG_ChannelName, "ChannelName", [Flags], [MinimumSeverity], [Color] );
+ ADD_LOGGING_CHANNEL_TAG( "Tag1" );
+ ADD_LOGGING_CHANNEL_TAG( "Tag2" );
+ END_DEFINE_LOGGING_CHANNEL();
+
+ These macros create a global channel ID variable with the name specified
+ by the first parameter (in this example, LOG_ChannelName). This channel ID
+ can be used by various LoggingSystem_** functions to manipulate the channel settings.
+
+ The optional [Flags] parameter is an OR'd together set of LoggingChannelFlags_t
+ values (default: 0).
+
+ The optional [MinimumSeverity] parameter is the lowest threshold
+ above which messages will be processed (inclusive). The default is LS_MESSAGE,
+ which results in all messages, warnings, and errors being logged.
+ Variadic parameters to the Log_** functions will be ignored if a channel
+ is not enabled for a given severity (for performance reasons).
+
+ Logging channels can have their minimum severity modified by name, ID, or tag.
+
+ Logging channels are not hierarchical since there are situations in which
+ a channel needs to belong to multiple hierarchies. Use tags to create
+ categories or shallow hierarchies.
+
+ @TODO (Feature wishlist):
+ 1) Callstack logging support
+ 2) Registering dynamic channels and unregistering channels at runtime
+ 3) Sentient robot to clean up the thousands of places using the old/legacy logging system.
+*/
+
+//////////////////////////////////////////////////////////////////////////
+// Constants, Types, Forward Declares
+//////////////////////////////////////////////////////////////////////////
+
+class CLoggingSystem;
+class CThreadFastMutex;
+
+//-----------------------------------------------------------------------------
+// Maximum length of a sprintf'ed logging message.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_MESSAGE_LENGTH = 2048;
+
+//-----------------------------------------------------------------------------
+// Maximum length of a channel or tag name.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_IDENTIFIER_LENGTH = 32;
+
+//-----------------------------------------------------------------------------
+// Maximum number of logging channels. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_CHANNEL_COUNT = 256;
+
+//-----------------------------------------------------------------------------
+// Maximum number of logging tags across all channels. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_TAG_COUNT = 1024;
+
+//-----------------------------------------------------------------------------
+// Maximum number of characters across all logging tags. Increase if needed.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_TAG_CHARACTER_COUNT = 8192;
+
+//-----------------------------------------------------------------------------
+// Maximum number of concurrent logging listeners in a given logging state.
+//-----------------------------------------------------------------------------
+const int MAX_LOGGING_LISTENER_COUNT = 16;
+
+//-----------------------------------------------------------------------------
+// An invalid color set on a channel to imply that it should use
+// a device-dependent default color where applicable.
+//-----------------------------------------------------------------------------
+const Color UNSPECIFIED_LOGGING_COLOR( 0, 0, 0, 0 );
+
+//-----------------------------------------------------------------------------
+// An ID returned by the logging system to refer to a logging channel.
+//-----------------------------------------------------------------------------
+typedef int LoggingChannelID_t;
+
+//-----------------------------------------------------------------------------
+// A sentinel value indicating an invalid logging channel ID.
+//-----------------------------------------------------------------------------
+const LoggingChannelID_t INVALID_LOGGING_CHANNEL_ID = -1;
+
+//-----------------------------------------------------------------------------
+// The severity of a logging operation.
+//-----------------------------------------------------------------------------
+enum LoggingSeverity_t
+{
+ //-----------------------------------------------------------------------------
+ // An informative logging message.
+ //-----------------------------------------------------------------------------
+ LS_MESSAGE = 0,
+
+ //-----------------------------------------------------------------------------
+ // A warning, typically non-fatal
+ //-----------------------------------------------------------------------------
+ LS_WARNING = 1,
+
+ //-----------------------------------------------------------------------------
+ // A message caused by an Assert**() operation.
+ //-----------------------------------------------------------------------------
+ LS_ASSERT = 2,
+
+ //-----------------------------------------------------------------------------
+ // An error, typically fatal/unrecoverable.
+ //-----------------------------------------------------------------------------
+ LS_ERROR = 3,
+
+ //-----------------------------------------------------------------------------
+ // A placeholder level, higher than any legal value.
+ // Not a real severity value!
+ //-----------------------------------------------------------------------------
+ LS_HIGHEST_SEVERITY = 4,
+};
+
+//-----------------------------------------------------------------------------
+// Action which should be taken by logging system as a result of
+// a given logged message.
+//
+// The logging system invokes ILoggingResponsePolicy::OnLog() on
+// the specified policy object, which returns a LoggingResponse_t.
+//-----------------------------------------------------------------------------
+enum LoggingResponse_t
+{
+ LR_CONTINUE,
+ LR_DEBUGGER,
+ LR_ABORT,
+};
+
+//-----------------------------------------------------------------------------
+// Logging channel behavior flags, set on channel creation.
+//-----------------------------------------------------------------------------
+enum LoggingChannelFlags_t
+{
+ //-----------------------------------------------------------------------------
+ // Indicates that the spew is only relevant to interactive consoles.
+ //-----------------------------------------------------------------------------
+ LCF_CONSOLE_ONLY = 0x00000001,
+
+ //-----------------------------------------------------------------------------
+ // Indicates that spew should not be echoed to any output devices.
+ // A suitable logging listener must be registered which respects this flag
+ // (e.g. a file logger).
+ //-----------------------------------------------------------------------------
+ LCF_DO_NOT_ECHO = 0x00000002,
+};
+
+//-----------------------------------------------------------------------------
+// A callback function used to register tags on a logging channel
+// during initialization.
+//-----------------------------------------------------------------------------
+typedef void ( *RegisterTagsFunc )();
+
+//-----------------------------------------------------------------------------
+// A context structure passed to logging listeners and response policy classes.
+//-----------------------------------------------------------------------------
+struct LoggingContext_t
+{
+ // ID of the channel being logged to.
+ LoggingChannelID_t m_ChannelID;
+ // Flags associated with the channel.
+ LoggingChannelFlags_t m_Flags;
+ // Severity of the logging event.
+ LoggingSeverity_t m_Severity;
+ // Color of logging message if one was specified to Log_****() macro.
+ // If not specified, falls back to channel color.
+ // If channel color is not specified, this value is UNSPECIFIED_LOGGING_COLOR
+ // and indicates that a suitable default should be chosen.
+ Color m_Color;
+};
+
+//-----------------------------------------------------------------------------
+// Interface for classes to handle logging output.
+//
+// The Log() function of this class is called synchronously and serially
+// by the logging system on all registered instances of ILoggingListener
+// in the current "logging state".
+//
+// Derived classes may do whatever they want with the message (write to disk,
+// write to console, send over the network, drop on the floor, etc.).
+//
+// In general, derived classes should do one, simple thing with the output
+// to allow callers to register multiple, orthogonal logging listener classes.
+//-----------------------------------------------------------------------------
+class ILoggingListener
+{
+public:
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Interface for policy classes which determine how to behave when a
+// message is logged.
+//
+// Can return:
+// LR_CONTINUE (continue execution)
+// LR_DEBUGGER (break into debugger if one is present, otherwise continue)
+// LR_ABORT (terminate process immediately with a failure code of 1)
+//-----------------------------------------------------------------------------
+class ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext ) = 0;
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Common Logging Listeners & Logging Response Policies
+//////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+// A basic logging listener which prints to stdout and the debug channel.
+//-----------------------------------------------------------------------------
+class CSimpleLoggingListener : public ILoggingListener
+{
+public:
+ CSimpleLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) :
+ m_bQuietPrintf( bQuietPrintf ),
+ m_bQuietDebugger( bQuietDebugger )
+ {
+ }
+
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+#ifdef _X360
+ if ( !m_bQuietDebugger && XBX_IsConsoleConnected() )
+ {
+ // send to console
+ XBX_DebugString( XMAKECOLOR( 0,0,0 ), pMessage );
+ }
+ else
+#endif
+ {
+#if !defined( _CERT ) && !defined( DBGFLAG_STRINGS_STRIP )
+ if ( !m_bQuietPrintf )
+ {
+ _tprintf( _T("%s"), pMessage );
+ }
+#endif
+
+#ifdef _WIN32
+ if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+#endif
+ }
+ }
+
+ // If set to true, does not print anything to stdout.
+ bool m_bQuietPrintf;
+ // If set to true, does not print anything to debugger.
+ bool m_bQuietDebugger;
+};
+
+//-----------------------------------------------------------------------------
+// A basic logging listener for GUI applications
+//-----------------------------------------------------------------------------
+class CSimpleWindowsLoggingListener : public ILoggingListener
+{
+public:
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+ if ( Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+ if ( pContext->m_Severity == LS_ERROR )
+ {
+ if ( Plat_IsInDebugSession() )
+ DebuggerBreak();
+
+ Plat_MessageBox( "Error", pMessage );
+ }
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+// ** NOTE FOR INTEGRATION **
+// This was copied over from source 2 rather than integrated because
+// source 2 has more significantly refactored tier0 logging.
+//
+// A logging listener with Win32 console API color support which which prints
+// to stdout and the debug channel.
+//-----------------------------------------------------------------------------
+#if !defined(_GAMECONSOLE)
+class CColorizedLoggingListener : public CSimpleLoggingListener
+{
+public:
+ CColorizedLoggingListener( bool bQuietPrintf = false, bool bQuietDebugger = false ) : CSimpleLoggingListener( bQuietPrintf, bQuietDebugger )
+ {
+ InitWin32ConsoleColorContext( &m_ColorContext );
+ }
+
+ virtual void Log( const LoggingContext_t *pContext, const tchar *pMessage )
+ {
+ if ( !m_bQuietPrintf )
+ {
+ int nPrevColor = -1;
+
+ if ( pContext->m_Color != UNSPECIFIED_LOGGING_COLOR )
+ {
+ nPrevColor = SetWin32ConsoleColor( &m_ColorContext,
+ pContext->m_Color.r(), pContext->m_Color.g(), pContext->m_Color.b(),
+ MAX( MAX( pContext->m_Color.r(), pContext->m_Color.g() ), pContext->m_Color.b() ) > 128 );
+ }
+
+ _tprintf( _T("%s"), pMessage );
+
+ if ( nPrevColor >= 0 )
+ {
+ RestoreWin32ConsoleColor( &m_ColorContext, nPrevColor );
+ }
+ }
+
+#ifdef _WIN32
+ if ( !m_bQuietDebugger && Plat_IsInDebugSession() )
+ {
+ Plat_DebugString( pMessage );
+ }
+#endif
+ }
+
+ Win32ConsoleColorContext_t m_ColorContext;
+};
+#endif // !_GAMECONSOLE
+
+
+//-----------------------------------------------------------------------------
+// Default logging response policy used when one is not specified.
+//-----------------------------------------------------------------------------
+class CDefaultLoggingResponsePolicy : public ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
+ {
+ if ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) )
+ {
+ return LR_DEBUGGER;
+ }
+ else if ( pContext->m_Severity == LS_ERROR )
+ {
+ return LR_ABORT;
+ }
+ else
+ {
+ return LR_CONTINUE;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+// A logging response policy which never terminates the process, even on error.
+//-----------------------------------------------------------------------------
+class CNonFatalLoggingResponsePolicy : public ILoggingResponsePolicy
+{
+public:
+ virtual LoggingResponse_t OnLog( const LoggingContext_t *pContext )
+ {
+ if ( ( pContext->m_Severity == LS_ASSERT && !CommandLine()->FindParm( "-noassert" ) ) || pContext->m_Severity == LS_ERROR )
+ {
+ return LR_DEBUGGER;
+ }
+ else
+ {
+ return LR_CONTINUE;
+ }
+ }
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Central Logging System
+//////////////////////////////////////////////////////////////////////////
+
+//-----------------------------------------------------------------------------
+// The central logging system.
+//
+// Multiple instances can exist, though all exported tier0 functionality
+// specifically works with a single global instance
+// (via GetGlobalLoggingSystem()).
+//-----------------------------------------------------------------------------
+class CLoggingSystem
+{
+public:
+ struct LoggingChannel_t;
+
+ CLoggingSystem();
+ ~CLoggingSystem();
+
+ //-----------------------------------------------------------------------------
+ // Register a logging channel with the logging system.
+ // The same channel can be registered multiple times, but the parameters
+ // in each call to RegisterLoggingChannel must either match across all calls
+ // or be set to defaults on any given call
+ //
+ // This function is not thread-safe and should generally only be called
+ // by a single thread. Using the logging channel definition macros ensures
+ // that this is called on the static initialization thread.
+ //-----------------------------------------------------------------------------
+ LoggingChannelID_t RegisterLoggingChannel( const char *pChannelName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t minimumSeverity = LS_MESSAGE, Color spewColor = UNSPECIFIED_LOGGING_COLOR );
+
+ //-----------------------------------------------------------------------------
+ // Gets a channel ID from a string name.
+ // Performs a simple linear search; cache the value whenever possible
+ // or re-register the logging channel to get a global ID.
+ //-----------------------------------------------------------------------------
+ LoggingChannelID_t FindChannel( const char *pChannelName ) const;
+
+ int GetChannelCount() const { return m_nChannelCount; }
+
+ //-----------------------------------------------------------------------------
+ // Gets a pointer to the logging channel description.
+ //-----------------------------------------------------------------------------
+ LoggingChannel_t *GetChannel( LoggingChannelID_t channelID );
+ const LoggingChannel_t *GetChannel( LoggingChannelID_t channelID ) const;
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel has the specified tag.
+ //-----------------------------------------------------------------------------
+ bool HasTag( LoggingChannelID_t channelID, const char *pTag ) const { return GetChannel( channelID )->HasTag( pTag ); }
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel has been initialized.
+ // The main purpose is catching m_nChannelCount being zero because no channels have been registered.
+ //-----------------------------------------------------------------------------
+ bool IsValidChannelID( LoggingChannelID_t channelID ) const { return ( channelID >= 0 ) && ( channelID < m_nChannelCount ); }
+
+ //-----------------------------------------------------------------------------
+ // Returns true if the given channel will spew at the given severity level.
+ //-----------------------------------------------------------------------------
+ bool IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity ) const { return IsValidChannelID( channelID ) && GetChannel( channelID )->IsEnabled( severity ); }
+
+ //-----------------------------------------------------------------------------
+ // Functions to set the spew level of a channel either directly by ID or
+ // string name, or for all channels with a given tag.
+ //
+ // These functions are not technically thread-safe but calling them across
+ // multiple threads should cause no significant problems
+ // (the underlying data types being changed are 32-bit/atomic).
+ //-----------------------------------------------------------------------------
+ void SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
+ void SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
+ void SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
+
+ //-----------------------------------------------------------------------------
+ // Gets or sets the color of a logging channel.
+ // (The functions are not thread-safe, but the consequences are not
+ // significant.)
+ //-----------------------------------------------------------------------------
+ Color GetChannelColor( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_SpewColor; }
+ void SetChannelColor( LoggingChannelID_t channelID, Color color ) { GetChannel( channelID )->m_SpewColor = color; }
+
+ //-----------------------------------------------------------------------------
+ // Gets or sets the flags on a logging channel.
+ // (The functions are not thread-safe, but the consequences are not
+ // significant.)
+ //-----------------------------------------------------------------------------
+ LoggingChannelFlags_t GetChannelFlags( LoggingChannelID_t channelID ) const { return GetChannel( channelID )->m_Flags; }
+ void SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags ) { GetChannel( channelID )->m_Flags = flags; }
+
+ //-----------------------------------------------------------------------------
+ // Adds a string tag to a channel.
+ // This is not thread-safe and should only be called by a RegisterTagsFunc
+ // callback passed in to RegisterLoggingChannel (via the
+ // channel definition macros).
+ //-----------------------------------------------------------------------------
+ void AddTagToCurrentChannel( const char *pTagName );
+
+ //-----------------------------------------------------------------------------
+ // Functions to save/restore the current logging state.
+ // Set bThreadLocal to true on a matching Push/Pop call if the intent
+ // is to override the logging listeners on the current thread only.
+ //
+ // Pushing the current logging state onto the state stack results
+ // in the current state being cleared by default (no listeners, default logging response policy).
+ // Set bClearState to false to copy the existing listener pointers to the new state.
+ //
+ // These functions which mutate logging state ARE thread-safe and are
+ // guarded by m_StateMutex.
+ //-----------------------------------------------------------------------------
+ void PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
+ void PopLoggingState( bool bThreadLocal = false );
+
+ //-----------------------------------------------------------------------------
+ // Registers a logging listener (a class which handles logged messages).
+ //-----------------------------------------------------------------------------
+ void RegisterLoggingListener( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Removes a logging listener from the registered list
+ //-----------------------------------------------------------------------------
+ void UnregisterLoggingListener( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Returns whether the specified logging listener is registered.
+ //-----------------------------------------------------------------------------
+ bool IsListenerRegistered( ILoggingListener *pListener );
+
+ //-----------------------------------------------------------------------------
+ // Clears out all of the current logging state (removes all listeners,
+ // sets the response policy to the default).
+ //-----------------------------------------------------------------------------
+ void ResetCurrentLoggingState();
+
+ //-----------------------------------------------------------------------------
+ // Sets a policy class to decide what should happen when messages of a
+ // particular severity are logged
+ // (e.g. exit on error, break into debugger).
+ // If pLoggingResponse is NULL, uses the default response policy class.
+ //-----------------------------------------------------------------------------
+ void SetLoggingResponsePolicy( ILoggingResponsePolicy *pLoggingResponse );
+
+ //-----------------------------------------------------------------------------
+ // Logs a message to the specified channel using a given severity and
+ // spew color. Passing in UNSPECIFIED_LOGGING_COLOR for 'color' allows
+ // the logging listeners to provide a default.
+ // NOTE: test 'IsChannelEnabled(channelID,severity)' before calling this!
+ //-----------------------------------------------------------------------------
+ LoggingResponse_t LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color color, const tchar *pMessage );
+
+ // Internal data to represent a logging tag
+ struct LoggingTag_t
+ {
+ const char *m_pTagName;
+ LoggingTag_t *m_pNextTag;
+ };
+
+ // Internal data to represent a logging channel.
+ struct LoggingChannel_t
+ {
+ bool HasTag( const char *pTag ) const
+ {
+ LoggingTag_t *pCurrentTag = m_pFirstTag;
+ while( pCurrentTag != NULL )
+ {
+ if ( stricmp( pCurrentTag->m_pTagName, pTag ) == 0 )
+ {
+ return true;
+ }
+ pCurrentTag = pCurrentTag->m_pNextTag;
+ }
+ return false;
+ }
+ bool IsEnabled( LoggingSeverity_t severity ) const { return severity >= m_MinimumSeverity; }
+ void SetSpewLevel( LoggingSeverity_t severity ) { m_MinimumSeverity = severity; }
+
+ LoggingChannelID_t m_ID;
+ LoggingChannelFlags_t m_Flags; // an OR'd combination of LoggingChannelFlags_t
+ LoggingSeverity_t m_MinimumSeverity; // The minimum severity level required to activate this channel.
+ Color m_SpewColor;
+ char m_Name[MAX_LOGGING_IDENTIFIER_LENGTH];
+ LoggingTag_t *m_pFirstTag;
+ };
+
+private:
+ // Represents the current state of the logger (registered listeners, response policy class, etc.) and can
+ // vary from thread-to-thread. It can also be pushed/popped to save/restore listener/response state.
+ struct LoggingState_t
+ {
+ // Index of the previous entry on the listener set stack.
+ int m_nPreviousStackEntry;
+
+ // Number of active listeners in this set. Cannot exceed MAX_LOGGING_LISTENER_COUNT.
+ // If set to -1, implies that this state structure is not in use.
+ int m_nListenerCount;
+ // Array of registered logging listener objects.
+ ILoggingListener *m_RegisteredListeners[MAX_LOGGING_LISTENER_COUNT];
+
+ // Specific policy class to determine behavior of logging system under specific message types.
+ ILoggingResponsePolicy *m_pLoggingResponse;
+ };
+
+ // These state functions to assume the caller has already grabbed the mutex.
+ LoggingState_t *GetCurrentState();
+ const LoggingState_t *GetCurrentState() const;
+
+ int FindUnusedStateIndex();
+ LoggingTag_t *AllocTag( const char *pTagName );
+
+ int m_nChannelCount;
+ LoggingChannel_t m_RegisteredChannels[MAX_LOGGING_CHANNEL_COUNT];
+
+ int m_nChannelTagCount;
+ LoggingTag_t m_ChannelTags[MAX_LOGGING_TAG_COUNT];
+
+ // Index to first free character in name pool.
+ int m_nTagNamePoolIndex;
+ // Pool of character data used for tag names.
+ char m_TagNamePool[MAX_LOGGING_TAG_CHARACTER_COUNT];
+
+ // Protects all data in this class except the registered channels
+ // (which are supposed to be registered using the macros at static/global init time).
+ // It is assumed that this mutex is reentrant safe on all platforms.
+ CThreadFastMutex *m_pStateMutex;
+
+ // The index of the current "global" state of the logging system. By default, all threads use this state
+ // for logging unless a given thread has pushed the logging state with bThreadLocal == true.
+ // If a thread-local state has been pushed, g_nThreadLocalStateIndex (a global thread-local integer) will be non-zero.
+ // By default, g_nThreadLocalStateIndex is 0 for all threads.
+ int m_nGlobalStateIndex;
+
+ // A pool of logging states used to store a stack (potentially per-thread).
+ static const int MAX_LOGGING_STATE_COUNT = 16;
+ LoggingState_t m_LoggingStates[MAX_LOGGING_STATE_COUNT];
+
+ // Default policy class which determines behavior.
+ CDefaultLoggingResponsePolicy m_DefaultLoggingResponse;
+
+ // Default spew function.
+ CSimpleLoggingListener m_DefaultLoggingListener;
+
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Logging Macros
+//////////////////////////////////////////////////////////////////////////
+
+// This macro will resolve to the most appropriate overload of LoggingSystem_Log() depending on the number of parameters passed in.
+#ifdef DBGFLAG_STRINGS_STRIP
+#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( Severity == LS_ERROR && LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
+#else
+#define InternalMsg( Channel, Severity, /* [Color], Message, */ ... ) do { if ( LoggingSystem_IsChannelEnabled( Channel, Severity ) ) LoggingSystem_Log( Channel, Severity, /* [Color], Message, */ ##__VA_ARGS__ ); } while( 0 )
+#endif
+
+//-----------------------------------------------------------------------------
+// New macros, use these!
+//
+// The macros take an optional Color parameter followed by the message
+// and the message formatting.
+// We rely on the variadic macro (__VA_ARGS__) operator to paste in the
+// extra parameters and resolve to the appropriate overload.
+//-----------------------------------------------------------------------------
+#define Log_Msg( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_MESSAGE, /* [Color], Message, */ ##__VA_ARGS__ )
+#define Log_Warning( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_WARNING, /* [Color], Message, */ ##__VA_ARGS__ )
+#define Log_Error( Channel, /* [Color], Message, */ ... ) InternalMsg( Channel, LS_ERROR, /* [Color], Message, */ ##__VA_ARGS__ )
+#ifdef DBGFLAG_STRINGS_STRIP
+#define Log_Assert( ... ) LR_CONTINUE
+#else
+#define Log_Assert( Message, ... ) LoggingSystem_LogAssert( Message, ##__VA_ARGS__ )
+#endif
+
+
+#define DECLARE_LOGGING_CHANNEL( Channel ) extern LoggingChannelID_t Channel
+
+#define DEFINE_LOGGING_CHANNEL_NO_TAGS( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
+ LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, NULL, ##__VA_ARGS__ )
+
+#define BEGIN_DEFINE_LOGGING_CHANNEL( Channel, ChannelName, /* [Flags], [Severity], [Color] */ ... ) \
+ static void Register_##Channel##_Tags(); \
+ LoggingChannelID_t Channel = LoggingSystem_RegisterLoggingChannel( ChannelName, Register_##Channel##_Tags, ##__VA_ARGS__ ); \
+ void Register_##Channel##_Tags() \
+ {
+
+#define ADD_LOGGING_CHANNEL_TAG( Tag ) LoggingSystem_AddTagToCurrentChannel( Tag )
+
+#define END_DEFINE_LOGGING_CHANNEL() \
+ }
+
+//////////////////////////////////////////////////////////////////////////
+// DLL Exports
+//////////////////////////////////////////////////////////////////////////
+
+// For documentation on these functions, please look at the corresponding function
+// in CLoggingSystem (unless otherwise specified).
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_RegisterLoggingChannel( const char *pName, RegisterTagsFunc registerTagsFunc, int flags = 0, LoggingSeverity_t severity = LS_MESSAGE, Color color = UNSPECIFIED_LOGGING_COLOR );
+
+PLATFORM_INTERFACE void LoggingSystem_RegisterLoggingListener( ILoggingListener *pListener );
+PLATFORM_INTERFACE void LoggingSystem_UnregisterLoggingListener( ILoggingListener *pListener );
+PLATFORM_INTERFACE void LoggingSystem_ResetCurrentLoggingState();
+PLATFORM_INTERFACE void LoggingSystem_SetLoggingResponsePolicy( ILoggingResponsePolicy *pResponsePolicy );
+// NOTE: PushLoggingState() saves the current logging state on a stack and results in a new clear state
+// (no listeners, default logging response policy).
+PLATFORM_INTERFACE void LoggingSystem_PushLoggingState( bool bThreadLocal = false, bool bClearState = true );
+PLATFORM_INTERFACE void LoggingSystem_PopLoggingState( bool bThreadLocal = false );
+
+PLATFORM_INTERFACE void LoggingSystem_AddTagToCurrentChannel( const char *pTagName );
+
+// Returns INVALID_LOGGING_CHANNEL_ID if not found
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_FindChannel( const char *pChannelName );
+PLATFORM_INTERFACE int LoggingSystem_GetChannelCount();
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetFirstChannelID();
+// Returns INVALID_LOGGING_CHANNEL_ID when there are no channels remaining.
+PLATFORM_INTERFACE LoggingChannelID_t LoggingSystem_GetNextChannelID( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE const CLoggingSystem::LoggingChannel_t *LoggingSystem_GetChannel( LoggingChannelID_t channelID );
+
+PLATFORM_INTERFACE bool LoggingSystem_HasTag( LoggingChannelID_t channelID, const char *pTag );
+
+PLATFORM_INTERFACE bool LoggingSystem_IsChannelEnabled( LoggingChannelID_t channelID, LoggingSeverity_t severity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevel( LoggingChannelID_t channelID, LoggingSeverity_t minimumSeverity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByName( const char *pName, LoggingSeverity_t minimumSeverity );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelSpewLevelByTag( const char *pTag, LoggingSeverity_t minimumSeverity );
+
+// Color is represented as an int32 due to C-linkage restrictions
+PLATFORM_INTERFACE int32 LoggingSystem_GetChannelColor( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelColor( LoggingChannelID_t channelID, int color );
+
+PLATFORM_INTERFACE LoggingChannelFlags_t LoggingSystem_GetChannelFlags( LoggingChannelID_t channelID );
+PLATFORM_INTERFACE void LoggingSystem_SetChannelFlags( LoggingChannelID_t channelID, LoggingChannelFlags_t flags );
+
+//-----------------------------------------------------------------------------
+// Logs a variable-argument to a given channel with the specified severity.
+// NOTE: if adding overloads to this function, remember that the Log_***
+// macros simply pass their variadic parameters through to LoggingSystem_Log().
+// Therefore, you need to ensure that the parameters are in the same general
+// order and that there are no ambiguities with the overload.
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, const char *pMessageFormat, ... ) FMTFUNCTION( 3, 4 );
+PLATFORM_OVERLOAD LoggingResponse_t LoggingSystem_Log( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessageFormat, ... ) FMTFUNCTION( 4, 5 );
+
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogDirect( LoggingChannelID_t channelID, LoggingSeverity_t severity, Color spewColor, const char *pMessage );
+PLATFORM_INTERFACE LoggingResponse_t LoggingSystem_LogAssert( const char *pMessageFormat, ... ) FMTFUNCTION( 1, 2 );
+
+#endif // LOGGING_H \ No newline at end of file
diff --git a/external/vpc/public/tier0/mem.h b/external/vpc/public/tier0/mem.h
new file mode 100644
index 0000000..ffb590b
--- /dev/null
+++ b/external/vpc/public/tier0/mem.h
@@ -0,0 +1,50 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Memory allocation!
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_MEM_H
+#define TIER0_MEM_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <stddef.h>
+
+
+#include "tier0/platform.h"
+
+#if !defined(STATIC_TIER0) && !defined(_STATIC_LINKED)
+
+#ifdef TIER0_DLL_EXPORT
+# define MEM_INTERFACE DLL_EXPORT
+#else
+# define MEM_INTERFACE DLL_IMPORT
+#endif
+
+#else // BUILD_AS_DLL
+
+#define MEM_INTERFACE extern
+
+#endif // BUILD_AS_DLL
+
+
+
+//-----------------------------------------------------------------------------
+// DLL-exported methods for particular kinds of memory
+//-----------------------------------------------------------------------------
+MEM_INTERFACE void *MemAllocScratch( int nMemSize );
+MEM_INTERFACE void MemFreeScratch();
+
+#if defined( POSIX )
+MEM_INTERFACE void ZeroMemory( void *mem, size_t length );
+#endif
+
+//Only works with USE_MEM_DEBUG and memory allocation call stack tracking enabled.
+MEM_INTERFACE int GetAllocationCallStack( void *mem, void **pCallStackOut, int iMaxEntriesOut );
+
+
+#endif /* TIER0_MEM_H */
diff --git a/external/vpc/public/tier0/memalloc.h b/external/vpc/public/tier0/memalloc.h
new file mode 100644
index 0000000..4254e74
--- /dev/null
+++ b/external/vpc/public/tier0/memalloc.h
@@ -0,0 +1,701 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header should never be used directly from leaf code!!!
+// Instead, just add the file memoverride.cpp into your project and all this
+// will automagically be used
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_MEMALLOC_H
+#define TIER0_MEMALLOC_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// These memory debugging switches aren't relevant under Linux builds since memoverride.cpp
+// isn't built into Linux projects
+#ifndef LINUX
+// Define this in release to get memory tracking even in release builds
+//#define USE_MEM_DEBUG 1
+
+// Define this in release to get light memory debugging
+//#define USE_LIGHT_MEM_DEBUG
+
+// Define this to require -uselmd to turn light memory debugging on
+//#define LIGHT_MEM_DEBUG_REQUIRES_CMD_LINE_SWITCH
+#endif
+
+#if defined( _MEMTEST )
+#if defined( _WIN32 ) || defined( _PS3 )
+#define USE_MEM_DEBUG 1
+#endif
+#endif
+
+
+#if defined( _PS3 )
+// Define STEAM_SHARES_GAME_ALLOCATOR to make Steam use the game's tier0 memory allocator.
+// This adds some memory to the game's Small Block Heap and Medium Block Heap, to compensate.
+// This configuration was disabled for Portal 2, as we could not sufficiently test it before ship.
+//#define STEAM_SHARES_GAME_ALLOCATOR
+#endif
+
+#if defined( STEAM_SHARES_GAME_ALLOCATOR )
+#define MBYTES_STEAM_SBH_USAGE 2
+#define MBYTES_STEAM_MBH_USAGE 4
+#else // STEAM_SHARES_GAME_ALLOCATOR
+#define MBYTES_STEAM_SBH_USAGE 0
+#define MBYTES_STEAM_MBH_USAGE 0
+#endif // STEAM_SHARES_GAME_ALLOCATOR
+
+// Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
+#define MEM_DEBUG_CLASSNAME 1
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+#include <stddef.h>
+#ifdef LINUX
+#undef offsetof
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+#endif
+
+#ifdef _PS3
+#define MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS 1
+#endif
+
+#include "tier0/mem.h"
+
+struct _CrtMemState;
+
+#define MEMALLOC_VERSION 1
+
+typedef size_t (*MemAllocFailHandler_t)( size_t );
+
+struct GenericMemoryStat_t
+{
+ const char *name;
+ int value;
+};
+
+
+// Virtual memory interface
+#include "tier0/memvirt.h"
+
+
+//-----------------------------------------------------------------------------
+// NOTE! This should never be called directly from leaf code
+// Just use new,delete,malloc,free etc. They will call into this eventually
+//-----------------------------------------------------------------------------
+abstract_class IMemAlloc
+{
+public:
+ // Release versions
+ virtual void *Alloc( size_t nSize ) = 0;
+public:
+ virtual void *Realloc( void *pMem, size_t nSize ) = 0;
+
+ virtual void Free( void *pMem ) = 0;
+ virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize ) = 0;
+
+ // Debug versions
+ virtual void *Alloc( size_t nSize, const char *pFileName, int nLine ) = 0;
+public:
+ virtual void *Realloc( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
+ virtual void Free( void *pMem, const char *pFileName, int nLine ) = 0;
+ virtual void *Expand_NoLongerSupported( void *pMem, size_t nSize, const char *pFileName, int nLine ) = 0;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+ virtual void *AllocAlign( size_t nSize, size_t align ) = 0;
+ virtual void *AllocAlign( size_t nSize, size_t align, const char *pFileName, int nLine ) = 0;
+ virtual void *ReallocAlign( void *pMem, size_t nSize, size_t align ) = 0;
+#endif
+
+ inline void *IndirectAlloc( size_t nSize ) { return Alloc( nSize ); }
+ inline void *IndirectAlloc( size_t nSize, const char *pFileName, int nLine ) { return Alloc( nSize, pFileName, nLine ); }
+
+ // Returns the size of a particular allocation (NOTE: may be larger than the size requested!)
+ virtual size_t GetSize( void *pMem ) = 0;
+
+ // Force file + line information for an allocation
+ virtual void PushAllocDbgInfo( const char *pFileName, int nLine ) = 0;
+ virtual void PopAllocDbgInfo() = 0;
+
+ // FIXME: Remove when we have our own allocator
+ // these methods of the Crt debug code is used in our codebase currently
+ virtual int32 CrtSetBreakAlloc( int32 lNewBreakAlloc ) = 0;
+ virtual int CrtSetReportMode( int nReportType, int nReportMode ) = 0;
+ virtual int CrtIsValidHeapPointer( const void *pMem ) = 0;
+ virtual int CrtIsValidPointer( const void *pMem, unsigned int size, int access ) = 0;
+ virtual int CrtCheckMemory( void ) = 0;
+ virtual int CrtSetDbgFlag( int nNewFlag ) = 0;
+ virtual void CrtMemCheckpoint( _CrtMemState *pState ) = 0;
+
+ // FIXME: Make a better stats interface
+ virtual void DumpStats() = 0;
+ virtual void DumpStatsFileBase( char const *pchFileBase ) = 0;
+ virtual size_t ComputeMemoryUsedBy( char const *pchSubStr ) = 0;
+
+ // FIXME: Remove when we have our own allocator
+ virtual void* CrtSetReportFile( int nRptType, void* hFile ) = 0;
+ virtual void* CrtSetReportHook( void* pfnNewHook ) = 0;
+ virtual int CrtDbgReport( int nRptType, const char * szFile,
+ int nLine, const char * szModule, const char * pMsg ) = 0;
+
+ virtual int heapchk() = 0;
+
+ virtual bool IsDebugHeap() = 0;
+
+ virtual void GetActualDbgInfo( const char *&pFileName, int &nLine ) = 0;
+ virtual void RegisterAllocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
+ virtual void RegisterDeallocation( const char *pFileName, int nLine, size_t nLogicalSize, size_t nActualSize, unsigned nTime ) = 0;
+
+ virtual int GetVersion() = 0;
+
+ virtual void CompactHeap() = 0;
+
+ // Function called when malloc fails or memory limits hit to attempt to free up memory (can come in any thread)
+ virtual MemAllocFailHandler_t SetAllocFailHandler( MemAllocFailHandler_t pfnMemAllocFailHandler ) = 0;
+
+ virtual void DumpBlockStats( void * ) = 0;
+
+ virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;
+
+ // Returns 0 if no failure, otherwise the size_t of the last requested chunk
+ virtual size_t MemoryAllocFailed() = 0;
+
+ virtual void CompactIncremental() = 0;
+
+ virtual void OutOfMemory( size_t nBytesAttempted = 0 ) = 0;
+
+ // Region-based allocations
+ virtual void *RegionAlloc( int region, size_t nSize ) = 0;
+ virtual void *RegionAlloc( int region, size_t nSize, const char *pFileName, int nLine ) = 0;
+
+ // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
+ virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
+
+ // Obtain virtual memory manager interface
+ virtual IVirtualMemorySection * AllocateVirtualMemorySection( size_t numMaxBytes ) = 0;
+
+ // Request 'generic' memory stats (returns a list of N named values; caller should assume this list will change over time)
+ virtual int GetGenericMemoryStats( GenericMemoryStat_t **ppMemoryStats ) = 0;
+
+ virtual ~IMemAlloc() { };
+
+ // handles storing allocation info for coroutines
+ virtual uint32 GetDebugInfoSize() = 0;
+ virtual void SaveDebugInfo( void *pvDebugInfo ) = 0;
+ virtual void RestoreDebugInfo( const void *pvDebugInfo ) = 0;
+ virtual void InitDebugInfo( void *pvDebugInfo, const char *pchRootFileName, int nLine ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Singleton interface
+//-----------------------------------------------------------------------------
+#ifdef _PS3
+
+PLATFORM_INTERFACE IMemAlloc * g_pMemAllocInternalPS3;
+#ifndef PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
+#define g_pMemAlloc g_pMemAllocInternalPS3
+#else
+#define g_pMemAlloc PLATFORM_INTERFACE_MEM_ALLOC_INTERNAL_PS3_OVERRIDE
+#endif
+
+#else // !_PS3
+
+MEM_INTERFACE IMemAlloc *g_pMemAlloc;
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef MEMALLOC_REGIONS
+#ifndef MEMALLOC_REGION
+#define MEMALLOC_REGION 0
+#endif
+inline void *MemAlloc_Alloc( size_t nSize )
+{
+ return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize );
+}
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->RegionAlloc( MEMALLOC_REGION, nSize, pFileName, nLine );
+}
+#else
+#undef MEMALLOC_REGION
+inline void *MemAlloc_Alloc( size_t nSize )
+{
+ return g_pMemAlloc->IndirectAlloc( nSize );
+}
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine );
+}
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef MEMALLOC_REGIONS
+#else
+#endif
+
+
+inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
+{
+ return (value & ( value - 1 )) == 0;
+}
+
+
+inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
+{
+#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ unsigned char *pAlloc, *pResult;
+
+#endif
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->AllocAlign( size, align );
+
+#else
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size ) ) == (unsigned char*)NULL)
+ return NULL;
+
+ pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
+ ((unsigned char**)(pResult))[-1] = pAlloc;
+
+ return (void *)pResult;
+
+#endif
+}
+
+inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
+{
+#ifndef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ unsigned char *pAlloc, *pResult;
+
+#endif
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->AllocAlign( size, align, pszFile, nLine );
+
+#else
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)MemAlloc_Alloc( sizeof(void *) + align + size, pszFile, nLine ) ) == (unsigned char*)NULL)
+ return NULL;
+
+ pResult = (unsigned char*)( (size_t)(pAlloc + sizeof(void *) + align ) & ~align );
+ ((unsigned char**)(pResult))[-1] = pAlloc;
+
+ return (void *)pResult;
+
+#endif
+}
+
+#ifdef USE_MEM_DEBUG
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
+#elif defined(USE_LIGHT_MEM_DEBUG)
+extern const char *g_pszModule;
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
+#else
+#define MemAlloc_AllocAligned( s, a ) MemAlloc_AllocAlignedUnattributed( s, a )
+#endif
+
+
+inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
+{
+ if ( !ValueIsPowerOfTwo( align ) )
+ return NULL;
+
+ // Don't change alignment between allocation + reallocation.
+ if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
+ return NULL;
+
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->ReallocAlign( ptr, size, align );
+
+#else
+
+ if ( !ptr )
+ return MemAlloc_AllocAligned( size, align );
+
+ void *pAlloc, *pResult;
+
+ // Figure out the actual allocation point
+ pAlloc = ptr;
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+ pAlloc = *( (void **)pAlloc );
+
+ // See if we have enough space
+ size_t nOffset = (size_t)ptr - (size_t)pAlloc;
+ size_t nOldSize = g_pMemAlloc->GetSize( pAlloc );
+ if ( nOldSize >= size + nOffset )
+ return ptr;
+
+ pResult = MemAlloc_AllocAligned( size, align );
+ memcpy( pResult, ptr, nOldSize - nOffset );
+ g_pMemAlloc->Free( pAlloc );
+ return pResult;
+
+#endif
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ g_pMemAlloc->Free( pMemBlock );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *( (void **)pAlloc );
+
+ g_pMemAlloc->Free( pAlloc );
+
+#endif
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ g_pMemAlloc->Free( pMemBlock, pszFile, nLine );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *( (void **)pAlloc );
+ g_pMemAlloc->Free( pAlloc, pszFile, nLine );
+
+#endif
+}
+
+inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
+{
+#ifdef MEMALLOC_SUPPORTS_ALIGNED_ALLOCATIONS
+
+ return g_pMemAlloc->GetSize( pMemBlock );
+
+#else
+
+ void *pAlloc;
+
+ if ( pMemBlock == NULL )
+ return 0;
+
+ pAlloc = pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (void *)(((size_t)pAlloc & ~( sizeof(void *) - 1 ) ) - sizeof(void *));
+
+ // pAlloc is the pointer to the start of memory block
+ pAlloc = *((void **)pAlloc );
+ return g_pMemAlloc->GetSize( pAlloc ) - ( (byte *)pMemBlock - (byte *)pAlloc );
+
+#endif
+}
+
+
+struct aligned_tmp_t
+{
+ // empty base class
+};
+
+// template here to allow adding alignment at levels of hierarchy that aren't the base
+template< int bytesAlignment = 16, class T = aligned_tmp_t >
+class CAlignedNewDelete : public T
+{
+public:
+ void *operator new( size_t nSize )
+ {
+ return MemAlloc_AllocAligned( nSize, bytesAlignment );
+ }
+
+ void* operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
+ {
+ return MemAlloc_AllocAlignedFileLine( nSize, bytesAlignment, pFileName, nLine );
+ }
+
+ void operator delete(void *pData)
+ {
+ if ( pData )
+ {
+ MemAlloc_FreeAligned( pData );
+ }
+ }
+
+ void operator delete( void* pData, int nBlockUse, const char *pFileName, int nLine )
+ {
+ if ( pData )
+ {
+ MemAlloc_FreeAligned( pData, pFileName, nLine );
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction memAllocAttributeAlloction( tag, __LINE__ )
+#define MemAlloc_PushAllocDbgInfo( pszFile, line ) g_pMemAlloc->PushAllocDbgInfo( pszFile, line )
+#define MemAlloc_PopAllocDbgInfo() g_pMemAlloc->PopAllocDbgInfo()
+#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
+#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) g_pMemAlloc->RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime )
+#else
+#define MEM_ALLOC_CREDIT_(tag) ((void)0)
+#define MemAlloc_PushAllocDbgInfo( pszFile, line ) ((void)0)
+#define MemAlloc_PopAllocDbgInfo() ((void)0)
+#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+
+class CMemAllocAttributeAlloction
+{
+public:
+ CMemAllocAttributeAlloction( const char *pszFile, int line )
+ {
+ MemAlloc_PushAllocDbgInfo( pszFile, line );
+ }
+
+ ~CMemAllocAttributeAlloction()
+ {
+ MemAlloc_PopAllocDbgInfo();
+ }
+};
+
+#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
+
+//-----------------------------------------------------------------------------
+
+#if defined(MSVC) && ( defined(_DEBUG) || defined(USE_MEM_DEBUG) )
+
+ #pragma warning(disable:4290)
+ #pragma warning(push)
+ #include <typeinfo.h>
+
+ // MEM_DEBUG_CLASSNAME is opt-in.
+ // Note: typeid().name() is not threadsafe, so if the project needs to access it in multiple threads
+ // simultaneously, it'll need a mutex.
+ #if defined(_CPPRTTI) && defined(MEM_DEBUG_CLASSNAME)
+
+ template <typename T> const char *MemAllocClassName( T *p )
+ {
+ static const char *pszName = typeid(*p).name(); // @TODO: support having debug heap ignore certain allocations, and ignore memory allocated here [5/7/2009 tom]
+ return pszName;
+ }
+
+ #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( MemAllocClassName( this ) )
+ #define MEM_ALLOC_CLASSNAME(type) (typeid((type*)(0)).name())
+ #else
+ #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( __FILE__ )
+ #define MEM_ALLOC_CLASSNAME(type) (__FILE__)
+ #endif
+
+ // MEM_ALLOC_CREDIT_FUNCTION is used when no this pointer is available ( inside 'new' overloads, for example )
+ #ifdef _MSC_VER
+ #define MEM_ALLOC_CREDIT_FUNCTION() MEM_ALLOC_CREDIT_( __FUNCTION__ )
+ #else
+ #define MEM_ALLOC_CREDIT_FUNCTION() (__FILE__)
+ #endif
+
+ #pragma warning(pop)
+#else
+ #define MEM_ALLOC_CREDIT_CLASS()
+ #define MEM_ALLOC_CLASSNAME(type) NULL
+ #define MEM_ALLOC_CREDIT_FUNCTION()
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+struct MemAllocFileLine_t
+{
+ const char *pszFile;
+ int line;
+};
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag ) \
+ static CUtlMap<void *, MemAllocFileLine_t, int> s_##tag##Allocs( DefLessFunc( void *) ); \
+ CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs = &s_##tag##Allocs; \
+ static CThreadFastMutex s_##tag##AllocsMutex; \
+ CThreadFastMutex * g_p##tag##AllocsMutex = &s_##tag##AllocsMutex; \
+ const char * g_psz##tag##Alloc = strcpy( (char *)MemAlloc_Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
+
+#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag ) \
+ extern CUtlMap<void *, MemAllocFileLine_t, int> * g_p##tag##Allocs; \
+ extern CThreadFastMutex *g_p##tag##AllocsMutex; \
+ extern const char * g_psz##tag##Alloc;
+
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
+ if ( fileLine.pszFile != g_psz##tag##Alloc ) \
+ { \
+ g_p##tag##Allocs->Insert( p, fileLine ); \
+ } \
+ \
+ MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ AUTO_LOCK_FM( *g_p##tag##AllocsMutex ); \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_p##tag##Allocs->Find( p ); \
+ if ( iRecordedFileLine != g_p##tag##Allocs->InvalidIndex() ) \
+ { \
+ fileLine = (*g_p##tag##Allocs)[iRecordedFileLine]; \
+ g_p##tag##Allocs->RemoveAt( iRecordedFileLine ); \
+ } \
+ \
+ MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#else
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MEMALLOC_DECLARE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
+#include <malloc.h>
+
+#define MEM_ALLOC_CREDIT_(tag) ((void)0)
+#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
+#define MEM_ALLOC_CREDIT_CLASS()
+#define MEM_ALLOC_CLASSNAME(type) NULL
+
+#define MemAlloc_PushAllocDbgInfo( pszFile, line )
+#define MemAlloc_PopAllocDbgInfo()
+
+#define MemAlloc_RegisterAllocation( a,b,c,d,e ) ((void)0)
+#define MemAlloc_RegisterDeallocation( a,b,c,d,e ) ((void)0)
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+inline void *MemAlloc_AllocAligned( size_t size, size_t align )
+{
+ return (void *)_aligned_malloc( size, align );
+}
+inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
+{
+ pszFile = pszFile;
+ nLine = nLine;
+ return (void *)_aligned_malloc( size, align );
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock )
+{
+ _aligned_free( pMemBlock );
+}
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile, int nLine )
+{
+ pszFile = pszFile;
+ nLine = nLine;
+ _aligned_free( pMemBlock );
+}
+
+#endif // !STEAM && NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+
+
+// linux memory tracking via hooks.
+#if defined( POSIX ) && !defined( _PS3 )
+PLATFORM_INTERFACE void MemoryLogMessage( char const *s ); // throw a message into the memory log
+PLATFORM_INTERFACE void EnableMemoryLogging( bool bOnOff );
+PLATFORM_INTERFACE void DumpMemoryLog( int nThresh );
+PLATFORM_INTERFACE void DumpMemorySummary( void );
+PLATFORM_INTERFACE void SetMemoryMark( void );
+PLATFORM_INTERFACE void DumpChangedMemory( int nThresh );
+
+// ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
+PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
+#else
+inline void MemoryLogMessage( char const * )
+{
+}
+inline void EnableMemoryLogging( bool )
+{
+}
+inline void DumpMemoryLog( int )
+{
+}
+inline void DumpMemorySummary( void )
+{
+}
+inline void SetMemoryMark( void )
+{
+}
+inline void DumpChangedMemory( int )
+{
+}
+inline size_t ApproximateProcessMemoryUsage( void )
+{
+ return 0;
+}
+#endif
+
+
+#endif /* TIER0_MEMALLOC_H */
diff --git a/external/vpc/public/tier0/memdbgoff.h b/external/vpc/public/tier0/memdbgoff.h
new file mode 100644
index 0000000..4d2c021
--- /dev/null
+++ b/external/vpc/public/tier0/memdbgoff.h
@@ -0,0 +1,25 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header, which must be the final line of a .h file,
+// causes all crt methods to stop using debugging versions of the memory allocators.
+// NOTE: Use memdbgon.h to re-enable memory debugging.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifdef MEM_OVERRIDE_ON
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef free
+#undef _expand
+#undef _msize
+#undef new
+#undef _aligned_malloc
+#undef _aligned_free
+#undef _malloc_dbg
+
+#undef MEM_OVERRIDE_ON
+
+#endif
diff --git a/external/vpc/public/tier0/memdbgon.h b/external/vpc/public/tier0/memdbgon.h
new file mode 100644
index 0000000..e66664d
--- /dev/null
+++ b/external/vpc/public/tier0/memdbgon.h
@@ -0,0 +1,281 @@
+//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This header, which must be the final include in a .cpp (or .h) file,
+// causes all crt methods to use debugging versions of the memory allocators.
+// NOTE: Use memdbgoff.h to disable memory debugging.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+// SPECIAL NOTE! This file must *not* use include guards; we need to be able
+// to include this potentially multiple times (since we can deactivate debugging
+// by including memdbgoff.h)
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+// SPECIAL NOTE #2: This must be the final include in a .cpp or .h file!!!
+
+#if defined(_DEBUG) && !defined(USE_MEM_DEBUG) && !defined( _PS3 )
+#define USE_MEM_DEBUG 1
+#endif
+
+// If debug build or ndebug and not already included MS custom alloc files, or already included this file
+#if (defined(_DEBUG) || !defined(_INC_CRTDBG)) || defined(MEMDBGON_H)
+
+#include "tier0/basetypes.h"
+
+#include "tier0/valve_off.h"
+ #ifdef COMPILER_MSVC
+ #include <tchar.h>
+ #else
+ #include <wchar.h>
+ #endif
+ #include <string.h>
+ #ifndef _PS3
+ #include <malloc.h>
+ #endif
+#include "tier0/valve_on.h"
+
+#include "commonmacros.h"
+#include "memalloc.h"
+
+#ifdef _WIN32
+#ifndef MEMALLOC_REGION
+#define MEMALLOC_REGION 0
+#endif
+#else
+#undef MEMALLOC_REGION
+#endif
+
+#if defined(USE_MEM_DEBUG)
+ #if defined( POSIX ) || defined( _PS3 )
+ #define _NORMAL_BLOCK 1
+
+ #include "tier0/valve_off.h"
+ #include <cstddef>
+ #include <new>
+ #include <sys/types.h>
+ #if !defined( DID_THE_OPERATOR_NEW )
+ #define DID_THE_OPERATOR_NEW
+ // posix doesn't have a new of this form, so we impl our own
+ void* operator new( size_t nSize, int blah, const char *pFileName, int nLine );
+ void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine );
+ #endif
+
+ #else // defined(POSIX)
+
+ // Include crtdbg.h and make sure _DEBUG is set to 1.
+ #if !defined(_DEBUG)
+ #define _DEBUG 1
+ #include <crtdbg.h>
+ #undef _DEBUG
+ #else
+ #include <crtdbg.h>
+ #endif // !defined(_DEBUG)
+
+ #endif // defined(POSIX)
+#endif
+
+#include "tier0/memdbgoff.h"
+
+// --------------------------------------------------------
+// Debug/non-debug agnostic elements
+
+#define MEM_OVERRIDE_ON 1
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef _expand
+#undef free
+#undef _msize
+#undef _aligned_malloc
+#undef _aligned_free
+
+#ifndef MEMDBGON_H
+inline void *MemAlloc_InlineCallocMemset( void *pMem, size_t nCount, size_t nElementSize)
+{
+ memset(pMem, 0, nElementSize * nCount);
+ return pMem;
+}
+#endif
+
+#define calloc(c, s) MemAlloc_InlineCallocMemset(malloc(c*s), c, s)
+#ifndef USE_LIGHT_MEM_DEBUG
+#define free(p) g_pMemAlloc->Free( p )
+#define _aligned_free( p ) MemAlloc_FreeAligned( p )
+#else
+extern const char *g_pszModule;
+#define free(p) g_pMemAlloc->Free( p, g_pszModule, 0 )
+#define _aligned_free( p ) MemAlloc_FreeAligned( p, g_pszModule, 0 )
+#endif
+#define _msize(p) g_pMemAlloc->GetSize( p )
+#define _expand(p, s) _expand_NoLongerSupported(p, s)
+
+// --------------------------------------------------------
+// Debug path
+#if defined(USE_MEM_DEBUG)
+
+#define malloc(s) MemAlloc_Alloc( s, __FILE__, __LINE__)
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAlignedFileLine( s, a, __FILE__, __LINE__ )
+
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+
+#undef new
+
+#if defined( _PS3 )
+ #ifndef PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ #define PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ inline void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ inline void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ #endif
+ #define new new( 1, __FILE__, __LINE__ )
+#elif !defined( GNUC )
+ #if defined(__AFX_H__) && defined(DEBUG_NEW)
+ #define new DEBUG_NEW
+ #else
+ #define MEMALL_DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
+ #define new MEMALL_DEBUG_NEW
+ #endif
+#endif
+
+#undef _strdup
+#undef strdup
+#undef _wcsdup
+#undef wcsdup
+
+#define _strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__)
+#define strdup(s) MemAlloc_StrDup(s, __FILE__, __LINE__)
+#define _wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__)
+#define wcsdup(s) MemAlloc_WcStrDup(s, __FILE__, __LINE__)
+
+// Make sure we don't define strdup twice
+#if !defined(MEMDBGON_H)
+
+inline char *MemAlloc_StrDup(const char *pString, const char *pFileName, unsigned nLine)
+{
+ char *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = strlen(pString) + 1;
+ if ((pMemory = (char *)MemAlloc_Alloc(len, pFileName, nLine)) != NULL)
+ {
+ return strcpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString, const char *pFileName, unsigned nLine)
+{
+ wchar_t *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = (wcslen(pString) + 1);
+ if ((pMemory = (wchar_t *)MemAlloc_Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+#endif // DBMEM_DEFINED_STRDUP
+
+#else
+// --------------------------------------------------------
+// Release path
+
+#ifndef USE_LIGHT_MEM_DEBUG
+#define malloc(s) MemAlloc_Alloc( s )
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a )
+#else
+#define malloc(s) MemAlloc_Alloc( s, g_pszModule, 0 )
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s, g_pszModule, 0 )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAlignedFileLine( s, a, g_pszModule, 0 )
+#endif
+
+#ifndef _malloc_dbg
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+#endif
+
+#undef new
+
+#if defined( _PS3 ) && !defined( _CERT )
+ #ifndef PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ #define PS3_OPERATOR_NEW_WRAPPER_DEFINED
+ inline void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ inline void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) { return g_pMemAlloc->IndirectAlloc( nSize, pFileName, nLine ); }
+ #endif
+ #define new new( 1, __FILE__, __LINE__ )
+#endif
+
+#undef _strdup
+#undef strdup
+#undef _wcsdup
+#undef wcsdup
+
+#define _strdup(s) MemAlloc_StrDup(s)
+#define strdup(s) MemAlloc_StrDup(s)
+#define _wcsdup(s) MemAlloc_WcStrDup(s)
+#define wcsdup(s) MemAlloc_WcStrDup(s)
+
+// Make sure we don't define strdup twice
+#if !defined(MEMDBGON_H)
+
+inline char *MemAlloc_StrDup(const char *pString)
+{
+ char *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = strlen(pString) + 1;
+ if ((pMemory = (char *)malloc(len)) != NULL)
+ {
+ return strcpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+inline wchar_t *MemAlloc_WcStrDup(const wchar_t *pString)
+{
+ wchar_t *pMemory;
+
+ if (!pString)
+ return NULL;
+
+ size_t len = (wcslen(pString) + 1);
+ if ((pMemory = (wchar_t *)malloc(len * sizeof(wchar_t))) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+#endif // DBMEM_DEFINED_STRDUP
+
+#endif // USE_MEM_DEBUG
+
+#define MEMDBGON_H // Defined here so can be used above
+
+#else
+
+#if defined(USE_MEM_DEBUG)
+#ifndef _STATIC_LINKED
+#pragma message ("Note: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build")
+#else
+#error "Error: file includes crtdbg.h directly, therefore will cannot use memdbgon.h in non-debug build. Not recoverable in static build"
+#endif
+#endif
+#endif // _INC_CRTDBG
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
diff --git a/external/vpc/public/tier0/memvirt.h b/external/vpc/public/tier0/memvirt.h
new file mode 100644
index 0000000..eeb0996
--- /dev/null
+++ b/external/vpc/public/tier0/memvirt.h
@@ -0,0 +1,46 @@
+//========== Copyright (C) Valve Corporation, All rights reserved. ==========//
+//
+// Purpose: CVirtualMemoryManager interface
+//
+//===========================================================================//
+
+#ifndef MEM_VIRT_H
+#define MEM_VIRT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#define VMM_KB ( 1024 )
+#define VMM_MB ( 1024 * VMM_KB )
+
+#ifdef _PS3
+// Total virtual address space reserved by CVirtualMemoryManager on startup:
+#define VMM_VIRTUAL_SIZE ( 512 * VMM_MB )
+#define VMM_PAGE_SIZE ( 64 * VMM_KB )
+#endif
+
+
+
+// Allocate virtual sections via IMemAlloc::AllocateVirtualMemorySection
+abstract_class IVirtualMemorySection
+{
+public:
+ // Information about memory section
+ virtual void * GetBaseAddress() = 0;
+ virtual size_t GetPageSize() = 0;
+ virtual size_t GetTotalSize() = 0;
+
+ // Functions to manage physical memory mapped to virtual memory
+ virtual bool CommitPages( void *pvBase, size_t numBytes ) = 0;
+ virtual void DecommitPages( void *pvBase, size_t numBytes ) = 0;
+
+ // Release the physical memory and associated virtual address space
+ virtual void Release() = 0;
+};
+
+// Get the IVirtualMemorySection associated with a given memory address (if any):
+extern IVirtualMemorySection *GetMemorySectionForAddress( void *pAddress );
+
+
+#endif // MEM_VIRT_H
diff --git a/external/vpc/public/tier0/minidump.h b/external/vpc/public/tier0/minidump.h
new file mode 100644
index 0000000..8f4b7b0
--- /dev/null
+++ b/external/vpc/public/tier0/minidump.h
@@ -0,0 +1,82 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef MINIDUMP_H
+#define MINIDUMP_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+// writes out a minidump of the current stack trace with a unique filename
+PLATFORM_INTERFACE void WriteMiniDump();
+
+typedef void (*FnWMain)( int , tchar *[] );
+
+#ifdef IS_WINDOWS_PC
+
+// calls the passed in function pointer and catches any exceptions/crashes thrown by it, and writes a minidump
+// use from wmain() to protect the whole program
+
+PLATFORM_INTERFACE void CatchAndWriteMiniDump( FnWMain pfn, int argc, tchar *argv[] );
+
+// The ExceptionInfo_t struct is a typeless data struct
+// which is OS-dependent and should never be used by external code.
+// Just pass it back into MinidumpSetUnhandledExceptionFunction
+struct ExceptionInfo_t;
+
+
+// Replaces the current function pointer with the one passed in.
+// Returns the previously-set function.
+// The function is called internally by WriteMiniDump() and CatchAndWriteMiniDump()
+// The default is the built-in function that uses DbgHlp.dll's MiniDumpWriteDump function
+typedef void (*FnMiniDump)( unsigned int uStructuredExceptionCode, ExceptionInfo_t * pExceptionInfo );
+PLATFORM_INTERFACE FnMiniDump SetMiniDumpFunction( FnMiniDump pfn );
+
+// Use this to write a minidump explicitly.
+// Some of the tools choose to catch the minidump themselves instead of using CatchAndWriteMinidump
+// so they can show their own dialog.
+//
+// ptchMinidumpFileNameBuffer if not-NULL should be a writable tchar buffer of length at
+// least _MAX_PATH and on return will contain the name of the minidump file written.
+// If ptchMinidumpFileNameBuffer is NULL the name of the minidump file written will not
+// be available after the function returns.
+//
+
+
+// NOTE: Matches windows.h
+enum MinidumpType_t
+{
+ MINIDUMP_Normal = 0x00000000,
+ MINIDUMP_WithDataSegs = 0x00000001,
+ MINIDUMP_WithFullMemory = 0x00000002,
+ MINIDUMP_WithHandleData = 0x00000004,
+ MINIDUMP_FilterMemory = 0x00000008,
+ MINIDUMP_ScanMemory = 0x00000010,
+ MINIDUMP_WithUnloadedModules = 0x00000020,
+ MINIDUMP_WithIndirectlyReferencedMemory = 0x00000040,
+ MINIDUMP_FilterModulePaths = 0x00000080,
+ MINIDUMP_WithProcessThreadData = 0x00000100,
+ MINIDUMP_WithPrivateReadWriteMemory = 0x00000200,
+ MINIDUMP_WithoutOptionalData = 0x00000400,
+ MINIDUMP_WithFullMemoryInfo = 0x00000800,
+ MINIDUMP_WithThreadInfo = 0x00001000,
+ MINIDUMP_WithCodeSegs = 0x00002000
+};
+
+PLATFORM_INTERFACE bool WriteMiniDumpUsingExceptionInfo(
+ unsigned int uStructuredExceptionCode,
+ ExceptionInfo_t *pExceptionInfo,
+ uint32 nMinidumpTypeFlags, // OR-ed together MinidumpType_t flags
+ tchar *ptchMinidumpFileNameBuffer = NULL
+ );
+
+PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction( FnMiniDump pfn );
+
+#endif
+
+#endif // MINIDUMP_H
diff --git a/external/vpc/public/tier0/p4performancecounters.h b/external/vpc/public/tier0/p4performancecounters.h
new file mode 100644
index 0000000..d0882b9
--- /dev/null
+++ b/external/vpc/public/tier0/p4performancecounters.h
@@ -0,0 +1,322 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef P4PERFORMANCECOUNTERS_H
+#define P4PERFORMANCECOUNTERS_H
+
+#pragma once
+// Pentium 4 support
+
+/*
+ http://developer.intel.com/design/Pentium4/documentation.htm
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 1: Basic Architecture
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 2A: Instruction Set Reference, A-M
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 2B: Instruction Set Reference, N-Z
+
+ IA-32 Intel Architecture Software Developer's Manual Volume 3: System Programming Guide
+
+
+ From Mikael Pettersson's perfctr:
+
+ http://user.it.uu.se/~mikpe/linux/perfctr/
+
+ * Known quirks:
+ - OVF_PMI+FORCE_OVF counters must have an ireset value of -1.
+ This allows the regular overflow check to also handle FORCE_OVF
+ counters. Not having this restriction would lead to MAJOR
+ complications in the driver's "detect overflow counters" code.
+ There is no loss of functionality since the ireset value doesn't
+ affect the counter's PMI rate for FORCE_OVF counters.
+
+ - In experiments with FORCE_OVF counters, and regular OVF_PMI
+ counters with small ireset values between -8 and -1, it appears
+ that the faulting instruction is subjected to a new PMI before
+ it can complete, ad infinitum. This occurs even though the driver
+ clears the CCCR (and in testing also the ESCR) and invokes a
+ user-space signal handler before restoring the CCCR and resuming
+ the instruction.
+*/
+
+#define NCOUNTERS 18
+
+// The 18 counters
+enum Counters
+{
+ MSR_BPU_COUNTER0,
+ MSR_BPU_COUNTER1,
+ MSR_BPU_COUNTER2,
+ MSR_BPU_COUNTER3,
+ MSR_MS_COUNTER0,
+ MSR_MS_COUNTER1,
+ MSR_MS_COUNTER2,
+ MSR_MS_COUNTER3,
+ MSR_FLAME_COUNTER0,
+ MSR_FLAME_COUNTER1,
+ MSR_FLAME_COUNTER2,
+ MSR_FLAME_COUNTER3,
+ MSR_IQ_COUNTER0,
+ MSR_IQ_COUNTER1,
+ MSR_IQ_COUNTER2,
+ MSR_IQ_COUNTER3,
+ MSR_IQ_COUNTER4,
+ MSR_IQ_COUNTER5
+};
+
+// register base for counters
+#define MSR_COUNTER_BASE 0x300
+
+// register base for CCCR register
+#define MSR_CCCR_BASE 0x360
+
+#pragma pack(push, 1)
+// access to these bits is through the methods
+typedef union ESCR
+{
+ struct
+ {
+ uint64 Reserved0_1 : 2; //
+ uint64 USR : 1; //
+ uint64 OS : 1; //
+ uint64 TagEnable : 1; //
+ uint64 TagValue : 4; //
+ uint64 EventMask : 16; // from event select
+ uint64 ESCREventSelect : 6; // 31:25 class of event
+ uint64 Reserved31 : 1; //
+
+ uint64 Reserved32_63 : 32; //
+ };
+ uint64 flat;
+
+} ESCR;
+
+typedef union CCCR
+{
+ struct
+ {
+ uint64 Reserved0_11 : 12;// 0 -11
+ uint64 Enable : 1; // 12
+ uint64 CCCRSelect : 3; // 13-15
+ uint64 Reserved16_17 : 2; // 16 17
+
+ uint64 Compare : 1; // 18
+ uint64 Complement : 1; // 19
+ uint64 Threshold : 4; // 20-23
+ uint64 Edge : 1; // 24
+ uint64 FORCE_OVF : 1; // 25
+ uint64 OVF_PMI : 1; // 26
+ uint64 Reserved27_29 : 3; // 27-29
+ uint64 Cascade : 1; // 30
+ uint64 OVF : 1; // 31
+
+ uint64 Reserved32_63 : 32; //
+ };
+ uint64 flat;
+
+} CCCR;
+
+#pragma pack(pop)
+
+extern const unsigned short cccr_escr_map[NCOUNTERS][8];
+
+enum P4TagState
+{
+ TagDisable, //
+ TagEnable, //
+};
+
+enum P4ForceOverflow
+{
+ ForceOverflowDisable,
+ ForceOverflowEnable,
+};
+
+enum P4OverflowInterrupt
+{
+ OverflowInterruptDisable,
+ OverflowInterruptEnable,
+};
+
+// Turn off the no return value warning in ReadCounter.
+#pragma warning( disable : 4035 )
+class P4BaseEvent
+{
+ int m_counter;
+
+protected:
+
+ void SetCounter(int counter)
+ {
+ m_counter = counter;
+ cccrPort = MSR_CCCR_BASE + m_counter;
+ counterPort = MSR_COUNTER_BASE + m_counter;
+ escrPort = cccr_escr_map[m_counter][cccr.CCCRSelect];
+ }
+
+public:
+
+ unsigned short m_eventMask;
+ const tchar *description;
+ PME *pme;
+ ESCR escr;
+ CCCR cccr;
+ int counterPort;
+ int cccrPort;
+ int escrPort;
+
+ P4BaseEvent()
+ {
+ pme = PME::Instance();
+ m_eventMask = 0;
+ description = _T("");
+ escr.flat = 0;
+ cccr.flat = 0;
+ cccr.Reserved16_17 = 3; // must be set
+ escrPort = 0;
+ m_counter = -1;
+ }
+
+ void StartCounter()
+ {
+ cccr.Enable = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void StopCounter()
+ {
+ cccr.Enable = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearCounter()
+ {
+ pme->WriteMSR( counterPort, 0ui64 ); // clear
+ }
+
+ void WriteCounter( int64 value )
+ {
+ pme->WriteMSR( counterPort, value ); // clear
+ }
+
+ int64 ReadCounter()
+ {
+#if PME_DEBUG
+ if ( escr.USR == 0 && escr.OS == 0 )
+ return -1; // no area to collect, use SetCaptureMode
+
+ if ( escr.EventMask == 0 )
+ return -2; // no event mask set
+
+ if ( m_counter == -1 )
+ return -3; // counter not legal
+#endif
+
+ // ReadMSR should work here too, but RDPMC should be faster
+ int64 value = 0;
+ pme->ReadMSR( counterPort, &value );
+ return value;
+#if 0
+ // we need to copy this into a temp for some reason
+ int temp = m_counter;
+ _asm
+ {
+ mov ecx, temp
+ RDPMC
+ }
+#endif
+ }
+
+ void SetCaptureMode( PrivilegeCapture priv )
+ {
+ switch ( priv )
+ {
+ case OS_Only:
+ {
+ escr.USR = 0;
+ escr.OS = 1;
+ break;
+ }
+ case USR_Only:
+ {
+ escr.USR = 1;
+ escr.OS = 0;
+ break;
+ }
+ case OS_and_USR:
+ {
+ escr.USR = 1;
+ escr.OS = 1;
+ break;
+ }
+ }
+
+ escr.EventMask = m_eventMask;
+ pme->WriteMSR( escrPort, escr.flat );
+ }
+
+ void SetTagging( P4TagState tagEnable, uint8 tagValue )
+ {
+ escr.TagEnable = tagEnable;
+ escr.TagValue = tagValue;
+ pme->WriteMSR( escrPort, escr.flat );
+ }
+
+ void SetFiltering( CompareState compareEnable, CompareMethod compareMethod, uint8 threshold, EdgeState edgeEnable )
+ {
+ cccr.Compare = compareEnable;
+ cccr.Complement = compareMethod;
+ cccr.Threshold = threshold;
+ cccr.Edge = edgeEnable;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void SetOverflowEnables( P4ForceOverflow overflowEnable, P4OverflowInterrupt overflowInterruptEnable )
+ {
+ cccr.FORCE_OVF = overflowEnable;
+ cccr.OVF_PMI = overflowInterruptEnable;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void SetOverflow()
+ {
+ cccr.OVF = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearOverflow()
+ {
+ cccr.OVF = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ bool isOverflow()
+ {
+ CCCR cccr_temp;
+ pme->ReadMSR( cccrPort, &cccr_temp.flat );
+ return cccr_temp.OVF;
+ }
+
+ void SetCascade()
+ {
+ cccr.Cascade = 1;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+
+ void ClearCascade()
+ {
+ cccr.Cascade = 0;
+ pme->WriteMSR( cccrPort, cccr.flat );
+ }
+};
+#pragma warning( default : 4035 )
+
+#include "eventmasks.h"
+#include "eventmodes.h"
+
+#endif // P4PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/p5p6performancecounters.h b/external/vpc/public/tier0/p5p6performancecounters.h
new file mode 100644
index 0000000..6e2d8b1
--- /dev/null
+++ b/external/vpc/public/tier0/p5p6performancecounters.h
@@ -0,0 +1,225 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef P5P6PERFORMANCECOUNTERS_H
+#define P5P6PERFORMANCECOUNTERS_H
+
+// defined for < Pentium 4
+
+//---------------------------------------------------------------------------
+// Format of the performance event IDs within this header file in case you
+// wish to add any additional events that may not be present here.
+//
+// BITS 0-8 Unit Mask, Unsed on P5 processors
+// BIT 9 Set if event can be set on counter 0
+// BIT 10 Set if event can be set on counter 1
+// BITS 11-15 Unused Set to zero
+// BITS 16-23 Event Select ID, Only bits 16-21 used on P5 Family
+// BITS 24-27 Unused set to zero
+// BITS 28-32 Process family that the event belong to, as returned by
+// the CPUID instruction.
+//---------------------------------------------------------------------------
+
+//---------------------------------------------------------------------------
+// PENTIUM PERFORMANCE COUNTERS.
+//---------------------------------------------------------------------------
+#define P5_DTCRD 0x50000300 //Data Cache Reads
+#define P5_DWRIT 0x50010300 //Data Cache Writes
+#define P5_DTTLB 0x50020300 //Data TLB Miss
+#define P5_DTRMS 0x50030300 //Data Read Misses
+#define P5_DWRMS 0x50040300 //Data Write Miss
+#define P5_WHLCL 0x50050300 //Write (Hit) to M- or E-state line
+#define P5_DCLWB 0x50060300 //Data Cache Lines Written Back
+#define P5_DCSNP 0x50070300 //External Snoops
+#define P5_DCSHT 0x50080300 //Data Cache Snoop Hits
+#define P5_MAIBP 0x50090300 //Memory Access in Both Pipes
+#define P5_BANKS 0x500A0300 //Bank Conflicts
+#define P5_MISAL 0x500B0300 //Misaligned Data Memory Reference
+#define P5_COCRD 0x500C0300 //Code Cache Reads
+#define P5_COTLB 0x500D0300 //Code TLB Misses
+#define P5_COCMS 0x500E0300 //Code Cache Misses
+#define P5_ANYSG 0x500F0300 //Any Segment Register Loaded
+#define P5_BRANC 0x50120300 //Branches
+#define P5_BTBHT 0x50130300 //BTB Hits
+#define P5_TBRAN 0x50140300 //Taken Branch or BTB hit
+#define P5_PFLSH 0x50150300 //Pipeline flushes
+#define P5_INSTR 0x50160300 //Instructions Executed
+#define P5_INSTV 0x50170300 //Instructions Executed in the V-Pipe (Pairing)
+#define P5_CLOCL 0x50180300 //Bus active
+#define P5_PSDWR 0x50190300 //Full write buffers
+#define P5_PSWDR 0x501A0300 //Waiting for Data Memory Read
+#define P5_NCLSW 0x501B0300 //Clocks stalled writing an E or M state line
+#define P5_IORWC 0x501D0300 //I/O Read or Write Cycle
+#define P5_NOCMR 0x501E0300 //Non-Cacheable Memory Reads
+#define P5_PSLDA 0x501F0300 //Clocks stalled due to AGI
+#define P5_FLOPS 0x50220300 //Floating Point Operations
+#define P5_DBGR0 0x50230300 //Breakpoint match on DR0
+#define P5_DBGR1 0x50240300 //Breakpoint match on DR1
+#define P5_DBGR2 0x50250300 //Breakpoint match on DR2
+#define P5_DBGR3 0x50260300 //Breakpoint match on DR3
+#define P5_HWINT 0x50270300 //Hardware interrupts
+#define P5_DTRWR 0x50280300 //Data reads or writes
+#define P5_DTRWM 0x50290300 //Data read or write miss
+#define P5_BOLAT 0x502A0100 //Bus ownership latency
+#define P5_BOTFR 0x502A0200 //Bus ownership transfer
+#define P5_MMXA1 0x502B0100 //MMX Instruction Executed in U-pipe
+#define P5_MMXA2 0x502B0200 //MMX Instruction Executed in V-pipe
+#define P5_MMXMS 0x502C0100 //Cache M state line sharing
+#define P5_MMSLS 0x502C0200 //Cache line sharing
+#define P5_MMXB1 0x502D0100 //EMMS Instructions Executed
+#define P5_MMXB2 0x502D0200 //Transition from MMX to FP instructions
+#define P5_NOCMW 0x502E0200 //Non-Cacheable Memory Writes
+#define P5_MMXC1 0x502F0100 //Saturated MMX Instructions Executed
+#define P5_MMXC2 0x502F0200 //Saturations Performed
+#define P5_MMXHS 0x50300100 //Cycles Not in HALT State
+#define P5_MMXD2 0x50310100 //MMX Data Read
+#define P5_MMXFP 0x50320100 //Floating Point Stalls
+#define P5_MMXTB 0x50320200 //Taken Branches
+#define P5_MMXD0 0x50330100 //D1 Starvation and FIFO Empty
+#define P5_MMXD1 0x50330200 //D1 Starvation and one instruction in FIFO
+#define P5_MMXE1 0x50340100 //MMX Data Writes
+#define P5_MMXE2 0x50340200 //MMX Data Write Misses
+#define P5_MMXWB 0x50350100 //Pipeline flushes, wrong branch prediction
+#define P5_MMXWJ 0x50350200 //Pipeline flushes, branch prediction WB-stage
+#define P5_MMXF1 0x50360100 //Misaligned MMX Data Memory Reference
+#define P5_MMXF2 0x50360200 //Pipeline Stalled Waiting for MMX data read
+#define P5_MMXRI 0x50370100 //Returns Predicted Incorrectly
+#define P5_MMXRP 0x50370200 //Returns Predicted
+#define P5_MMXG1 0x50380100 //MMX Multiply Unit Interlock
+#define P5_MMXG2 0x50380200 //MOVD/MOVQ store stall, previous operation
+#define P5_MMXRT 0x50390100 //Returns
+#define P5_MMXRO 0x50390200 //RSB Overflows
+#define P5_MMXBF 0x503A0100 //BTB False entries
+#define P5_MMXBM 0x503A0200 //BTB misprediction on a Not-Taken Branch
+#define P5_PXDWR 0x503B0100 //stalled due MMX Full write buffers
+#define P5_PXZWR 0x503B0200 //stalled on MMX write to E or M state line
+
+#define P5_CLOCK 0x503F0300 //Special value to count clocks on P5
+
+
+//---------------------------------------------------------------------------
+// PENTIUM PRO / PENTIUM II PERFORMANCE COUNTERS.
+//---------------------------------------------------------------------------
+#define P6_STRBB 0x60030300 //Store Buffer Block
+#define P6_STBDC 0x60040300 //Store Buffer Drain Cycles
+#define P6_MISMM 0x60050300 //Misaligned Data Memory Reference
+#define P6_SEGLD 0x60060300 //Segment register loads
+#define P6_FPOPE 0x60100100 //FP Computational Op. (COUNTER 0 ONLY)
+#define P6_FPEOA 0x60110200 //FP Microcode Exceptions (COUNTER 1 ONLY)
+#define P6_FMULT 0x60120200 //Multiplies (COUNTER 1 ONLY)
+#define P6_FPDIV 0x60130200 //Divides (COUNTER 1 ONLY)
+#define P6_DBUSY 0x60140200 //Cycles Divider Busy (COUNTER 1 ONLY)
+#define P6_L2STR 0x60210300 //L2 address strobes => address bus utilization
+#define P6_L2BBS 0x60220300 //Cycles L2 Bus Busy
+#define P6_L2BBT 0x60230300 //Cycles L2 Bus Busy transferring data to CPU
+#define P6_L2ALO 0x60240300 //L2 Lines Allocated
+#define P6_L2MAL 0x60250300 //L2 M-state Lines Allocated
+#define P6_L2CEV 0x60260300 //L2 Lines Evicted
+#define P6_L2MEV 0x60270300 //L2 M-state Lines Evicted
+#define P6_L2MCF 0x60280301 //L2 Cache Instruction Fetch Misses
+#define P6_L2FET 0x6028030F //L2 Cache Instruction Fetches
+#define P6_L2DRM 0x60290301 //L2 Cache Read Misses
+#define P6_L2DMR 0x6029030F //L2 Cache Reads
+#define P6_L2DWM 0x602A0301 //L2 Cache Write Misses
+#define P6_L2DMW 0x602A030F //L2 Cache Writes
+#define P6_L2CMS 0x602E0301 //L2 Cache Request Misses
+#define P6_L2DCR 0x602E030F //L2 Cache Requests
+#define P6_DMREF 0x60430300 //Data Memory References
+#define P6_DCALO 0x6045030F //L1 Lines Allocated
+#define P6_DCMAL 0x60460300 //L1 M-state Data Cache Lines Allocated
+#define P6_DCMEV 0x60470300 //L1 M-state Data Cache Lines Evicted
+#define P6_DCOUT 0x60480300 //L1 Misses outstanding
+#define P6_TSMCD 0x60520300 //Time Self-Modifiying Code Detected
+#define P6_BRWRA 0x60600300 //External Bus Cycles While Receive Active
+#define P6_BRDCD 0x60600300 //External Bus Request Outstanding
+#define P6_BRBNR 0x60610300 //External Bus Cycles While BNR Asserted
+#define P6_BUSBS 0x60620300 //External Bus Cycles-DRDY Asserted (busy)
+#define P6_BLOCK 0x60630300 //External Bus Cycles-LOCK signal asserted
+#define P6_BBRCV 0x60640300 //External Bus Cycles-Processor receiving data
+#define P6_BURST 0x60650300 //External Bus Burst Read Operations
+#define P6_BRINV 0x60660300 //External Bus Read for Ownership Transaction
+#define P6_BMLEV 0x60670300 //External Bus Writeback M-state Evicted
+#define P6_BBIFT 0x60680300 //External Bus Burst Instruction Fetches
+#define P6_BINVL 0x60690300 //External Bus Invalidate Transactions
+#define P6_BPRBT 0x606A0300 //External Bus Partial Read Transactions
+#define P6_BPTMO 0x606B0300 //External Bus Partial Memory Transactions
+#define P6_BUSIO 0x606C0300 //External Bus I/O Bus Transactions
+#define P6_BUSDF 0x606D0300 //External Bus Deferred Transactions
+#define P6_BUSTB 0x606E0300 //External Bus Burst Transactions
+#define P6_BMALL 0x606F0300 //External Bus Memory Transactions
+#define P6_BSALL 0x60700300 //External Bus Transactions
+#define P6_CLOCK 0x60790300 //Clockticks
+#define P6_BRHIT 0x607A0300 //External Bus Cycles While HIT Asserted
+#define P6_BRHTM 0x607B0300 //External Bus Cycles While HITM Asserted
+#define P6_BRSST 0x607E0300 //External Bus Cycles While Snoop Stalled
+#define P6_CMREF 0x60800300 //Total Instruction Fetches
+#define P6_TOIFM 0x60810300 //Total Instruction Fetch Misses
+#define P6_INTLB 0x60850300 //Instructions TLB Misses
+#define P6_CSFET 0x60860300 //Cycles Instruction Fetch Stalled
+#define P6_FTSTL 0x60870300 //Cycles Instruction Fetch stalled
+#define P6_RSTAL 0x60A20300 //Resource Related Stalls
+#define P6_MMXIE 0x60B00300 //MMX Instructions Executed
+#define P6_SAISE 0x60B10300 //Saturated Arithmetic Instructions Executed
+#define P6_PORT0 0x60B20301 //MMX micro-ops executed on Port 0
+#define P6_PORT1 0x60B20302 //MMX micro-ops executed on Port 1
+#define P6_PORT2 0x60B20304 //MMX micro-ops executed on Port 2
+#define P6_PORT3 0x60B20308 //MMX micro-ops executed on Port 3
+#define P6_MMXPA 0x60B30300 //MMX Packed Arithmetic
+#define P6_MMXPM 0x60B30301 //MMX Packed Multiply
+#define P6_MMXPS 0x60B30302 //MMX Packed Shift
+#define P6_MMXPO 0x60B30304 //MMX Packed Operations
+#define P6_MMXUO 0x60B30308 //MMX Unpacked Operations
+#define P6_MMXPL 0x60B30310 //MMX Packed Logical
+#define P6_INSTR 0x60C00300 //Instructions Retired
+#define P6_FPOPS 0x60C10100 //FP operations retired (COUNTER 0 ONLY)
+#define P6_UOPSR 0x60C20300 //Micro-Ops Retired
+#define P6_BRRET 0x60C40300 //Branch Instructions Retired
+#define P6_BRMSR 0x60C50300 //Branch Mispredictions Retired
+#define P6_MASKD 0x60C60300 //Clocks while interrupts masked
+#define P6_MSKPN 0x60C70300 //Clocks while interrupt is pending
+#define P6_HWINT 0x60C80300 //Hardware Interrupts Received
+#define P6_BTAKR 0x60C90300 //Taken Branch Retired
+#define P6_BTAKM 0x60CA0300 //Taken Branch Mispredictions
+#define P6_FPMMX 0x60CC0301 //Transitions from Floating Point to MMX
+#define P6_MMXFP 0x60CC0300 //Transitions from MMX to Floating Point
+#define P6_SIMDA 0x60CD0300 //SIMD Assists (EMMS Instructions Executed)
+#define P6_MMXIR 0x60CE0300 //MMX Instructions Retired
+#define P6_SAISR 0x60CF0300 //Saturated Arithmetic Instructions Retired
+#define P6_INSTD 0x60D00300 //Instructions Decoded
+#define P6_NPRTL 0x60D20300 //Renaming Stalls
+#define P6_SRSES 0x60D40301 //Segment Rename Stalls - ES
+#define P6_SRSDS 0x60D40302 //Segment Rename Stalls - DS
+#define P6_SRSFS 0x60D40304 //Segment Rename Stalls - FS
+#define P6_SRSGS 0x60D40308 //Segment Rename Stalls - GS
+#define P6_SRSXS 0x60D4030F //Segment Rename Stalls - ES DS FS GS
+#define P6_SRNES 0x60D50301 //Segment Renames - ES
+#define P6_SRNDS 0x60D50302 //Segment Renames - DS
+#define P6_SRNFS 0x60D50304 //Segment Renames - FS
+#define P6_SRNGS 0x60D50308 //Segment Renames - GS
+#define P6_SRNXS 0x60D5030F //Segment Renames - ES DS FS GS
+#define P6_BRDEC 0x60E00300 //Branch Instructions Decoded
+#define P6_BTBMS 0x60E20301 //BTB Misses
+#define P6_RETDC 0x60E40300 //Bogus Branches
+#define P6_BACLR 0x60E60300 //BACLEARS Asserted (Testing)
+
+
+
+
+
+
+// INTEL
+#define PENTIUM_FAMILY 5 // define for pentium
+#define PENTIUMPRO_FAMILY 6 // define for pentium pro
+#define PENTIUM4_FAMILY 15 // define for pentium 4
+
+
+// AMD
+#define K6_FAMILY 5
+#define K8_FAMILY 6
+#define EXTENDED_FAMILY 15 // AMD 64 and AMD Opteron
+
+#endif // P5P6PERFORMANCECOUNTERS_H
diff --git a/external/vpc/public/tier0/platform.h b/external/vpc/public/tier0/platform.h
new file mode 100644
index 0000000..4dad5df
--- /dev/null
+++ b/external/vpc/public/tier0/platform.h
@@ -0,0 +1,2032 @@
+//===== Copyright 1997-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+
+#ifdef SN_TARGET_PS3
+
+#define _PS3 1
+#define COMPILER_PS3 1
+#define PLATFORM_PS3 1
+
+// There are 2 compilers for the PS3: GCC and the SN Systems compiler.
+// They are mostly similar, but in a few places we need to distinguish between the two.
+#if defined( __SNC__ )
+#define COMPILER_SNC 1
+#elif defined( __GCC__ )
+#define COMPILER_GCC 1
+#else
+#error "Unrecognized PS3 compiler; either __SNC__ or __GCC__ must be defined"
+#endif
+
+#endif // SN_TARGET_PS3
+
+#ifdef __GCC__
+#define COMPILER_GCC 1
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define PLATFORM_PPC 1
+#endif
+
+
+#ifdef COMPILER_MSVC
+#pragma once
+#endif
+
+#if defined (_PS3)
+ #include <ppu_intrinsics.h>
+
+ // We want to force the assert to be redefined, because the STD assert might have been
+ // included and redefined. ps3_assert.h will do a check for assert being redefined.
+ // #include "ps3/ps3_assert.h"
+ #ifndef COMPILER_PS3
+ #error "for PS3, VPC must define COMPILER_PS3 macro just like it does for COMPILER_MSVCX360 macro"
+ #endif
+ #if !defined( COMPILER_SNC ) && !defined( COMPILER_GCC )
+ #error "for PS3, VPC must define COMPILER_SNC or COMPILER_GCC macro, depending on the target compiler, just like it does for COMPILER_MSVCX360 macro"
+ #endif
+
+#elif defined( _X360 )
+ #define NO_STEAM
+ #define NO_VOICE
+ // for the 360, the ppc platform and the rtos are tightly coupled
+ // setup the 360 environment here !once! for much less leaf module include wackiness
+ // these are critical order and purposely appear *before* anything else
+ #define _XBOX
+ #include <xaudio2.h>
+ #include <xbdm.h>
+ #include <xgraphics.h>
+ #include <xui.h>
+ #include <pmcpbsetup.h>
+ #include <xmahardwareabstraction.h>
+ #undef _XBOX
+
+#endif
+
+#include "wchartypes.h"
+#include "tier0/valve_off.h"
+
+#ifdef _PS3
+
+ #include "ps3/ps3_platform.h"
+
+ #define NO_STEAM_GAMECOORDINATOR
+
+#else
+
+ #include <malloc.h>
+ #include <memory.h>
+ #include <limits.h>
+ #include <float.h>
+ #include <stdlib.h>
+ #include <string.h>
+#ifdef OSX
+ #include <signal.h>
+#endif
+
+#endif
+
+// This macro
+#if defined( _PS3 ) && defined ( COMPILER_SNC )
+
+// There are known bugs in the PS3 optimizer. The following macros allow us to lower optimization for a subset of a file
+// If you run into build problems with optimization on, try turning off optimization for the selected file. If that
+// fixes the problem, use process of elimination and the below macros to find the bare minimum that needs to be
+// unoptimized and report the compiler issue to Sony as well.
+//
+// The correlation between optimization levels and numbers passed to the _Pragma xopt and postopt calls is as follows:
+// See: Control-group reference tables / -Xshow
+// .... xopt
+// -O1 0
+// -O2 5
+// -O3 5
+//
+// These macros MUST be used in pairs - Otherwise, the compiler will barf 'At end of source: error 67: expected a "}"'
+
+// xopt disables some of the miscellaneous optimizations
+#if __option(xopt)
+#define SN_OPT_DISABLE extern "C++" { _Pragma("control %push xopt=0")
+#define SN_OPT_ENABLE _Pragma("control %pop xopt") }
+#else // !__option(xopt)
+#define SN_OPT_DISABLE
+#define SN_OPT_ENABLE
+#endif // !__option(xopt)
+
+// postopt disables the main optimizer
+#if __option(postopt) > 0
+#define SN_MAIN_OPT_DISABLE extern "C++" { _Pragma("control %push postopt=0")
+#define SN_MAIN_OPT_ENABLE _Pragma("control %pop postopt") }
+#else // !__option(postopt) > 0
+#define SN_MAIN_OPT_DISABLE
+#define SN_MAIN_OPT_ENABLE
+#endif // !__option(postopt) > 0
+
+#else // ! ( _PS3 && COMPILER_SNC )
+#define SN_OPT_DISABLE
+#define SN_OPT_ENABLE
+#define SN_MAIN_OPT_DISABLE
+#define SN_MAIN_OPT_ENABLE
+#endif // ! ( _PS3 && COMPILER_SNC )
+
+#ifdef __cplusplus
+#if defined( COMPILER_GCC ) || defined( COMPILER_PS3 )
+ #include <new>
+#else
+ #include <new.h>
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Old-school defines we don't want to use moving forward
+//-----------------------------------------------------------------------------
+#if CROSS_PLATFORM_VERSION < 1
+
+// feature enables
+#define NEW_SOFTWARE_LIGHTING
+#if !defined( _X360 )
+#define SUPPORT_PACKED_STORE
+#endif
+
+#if defined( BINK_VIDEO ) && ( defined( _X360 ) || defined( _PS3 ) )
+#define BINK_ENABLED_FOR_CONSOLE
+#endif
+
+#if !defined( PORTAL2 )
+//#define PORTAL2
+#endif
+
+// C functions for external declarations that call the appropriate C++ methods
+#ifndef EXPORT
+ #ifdef _WIN32
+ #define EXPORT _declspec( dllexport )
+ #else
+ #define EXPORT /* */
+ #endif
+#endif
+
+#endif // CROSS_PLATFORM_VERSION < 1
+
+#if defined(_STATIC_LINKED)
+#include "staticlink/system.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// NOTE: All compiler defines are set up in the base VPC scripts
+// COMPILER_MSVC, COMPILER_MSVC32, COMPILER_MSVC64, COMPILER_MSVCX360
+// COMPILER_GCC
+// The rationale for this is that we need COMPILER_MSVC for the pragma blocks
+// #pragma once that occur at the top of all header files, therefore we can't
+// place the defines for these in here.
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Set up platform defines.
+//-----------------------------------------------------------------------------
+#ifdef _WIN32
+ #define IsPlatformLinux() 0
+ #define IsPlatformPosix() 0
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define IsPlatformPS3() 0
+ #define IsPlatformPS3_PPU() 0
+ #define IsPlatformPS3_SPU() 0
+ #define PLATFORM_WINDOWS 1
+ #define PLATFORM_OPENGL 0
+
+ #ifndef _X360
+ #define IsPlatformX360() 0
+ #define IsPlatformWindowsPC() 1
+ #define PLATFORM_WINDOWS_PC 1
+
+ #ifdef _WIN64
+ #define IsPlatformWindowsPC64() 1
+ #define IsPlatformWindowsPC32() 0
+ #define PLATFORM_WINDOWS_PC64 1
+ #else
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 1
+ #define PLATFORM_WINDOWS_PC32 1
+ #endif
+
+ #else // _X360
+
+ #define IsPlatformWindowsPC() 0
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 0
+ #define IsPlatformX360() 1
+ #define PLATFORM_X360 1
+
+ #endif // _X360
+#elif defined(_PS3)
+
+
+#define IsPlatformX360() 0
+#define IsPlatformPS3() 1
+#ifdef SPU
+#define IsPlatformPS3_PPU() 0
+#define IsPlatformPS3_SPU() 1
+#else
+#define IsPlatformPS3_PPU() 1
+#define IsPlatformPS3_SPU() 0
+#endif
+#define IsPlatformWindowsPC() 0
+#define IsPlatformWindowsPC64() 0
+#define IsPlatformWindowsPC32() 0
+#define IsPlatformPosix() 1
+#define PLATFORM_POSIX 1
+#define PLATFORM_OPENGL 0
+
+#define IsPlatformLinux() 0
+#define IsPlatformOSX() 0
+#define IsOSXOpenGL() 0
+
+
+#elif defined(POSIX)
+ #define IsPlatformX360() 0
+ #define IsPlatformPS3() 0
+ #define IsPlatformPS3_PPU() 0
+ #define IsPlatformPS3_SPU() 0
+ #define IsPlatformWindowsPC() 0
+ #define IsPlatformWindowsPC64() 0
+ #define IsPlatformWindowsPC32() 0
+ #define IsPlatformPosix() 1
+ #define PLATFORM_POSIX 1
+
+ #if defined( LINUX ) && !defined( OSX ) // for havok we define both symbols, so don't let the osx build wander down here
+ #define IsPlatformLinux() 1
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define PLATFORM_OPENGL 0
+ #define PLATFORM_LINUX 1
+ #elif defined ( OSX )
+ #define IsPlatformLinux() 0
+ #define IsPlatformOSX() 1
+ #define IsOSXOpenGL() 1
+ #define PLATFORM_OSX 1
+ #define PLATFORM_OPENGL 1
+ #else
+ #define IsPlatformLinux() 0
+ #define IsPlatformOSX() 0
+ #define IsOSXOpenGL() 0
+ #define PLATFORM_OPENGL 0
+ #endif
+
+#else
+ #error
+#endif
+
+// IsXXXX platform pseudo-functions
+#if ( defined( PLATFORM_WINDOWS ) && ( PLATFORM_WINDOWS ) )
+#define IsPlatformWindows() 1
+#else
+#define IsPlatformWindows() 0
+#endif
+
+#if ( defined( PLATFORM_OPENGL ) && PLATFORM_OPENGL )
+#define IsOpenGL() 1
+#else
+#define IsOpenGL() 0
+#endif
+
+
+
+#ifndef _PS3
+//#include <malloc.h>
+//#include <new.h>
+#else
+#include <stdlib.h> // For malloc()
+#include <alloca.h> // for alloca()
+#define _alloca alloca
+ #ifdef __cplusplus
+ #include <new>
+ #endif
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Old-school defines we're going to support since much code uses them
+//-----------------------------------------------------------------------------
+#if CROSS_PLATFORM_VERSION < 2
+
+#define IsLinux() IsPlatformLinux()
+#define IsOSX() IsPlatformOSX()
+#define IsPosix() IsPlatformPosix()
+#define IsX360() IsPlatformX360()
+#define IsPS3() IsPlatformPS3()
+
+// Setup platform defines.
+#ifdef COMPILER_MSVC
+#define MSVC 1
+#endif
+
+#ifdef COMPILER_GCC
+#define GNUC 1
+#endif
+
+#if defined( _WIN32 )
+#define _WINDOWS 1
+#endif
+
+#ifdef PLATFORM_WINDOWS_PC
+#define IS_WINDOWS_PC 1
+#endif
+
+#endif // CROSS_PLATFORM_VERSION < 2
+
+// VXConsole is enabled for...
+#if defined(_X360) || defined(_PS3)
+#define USE_VXCONSOLE 1
+#define HasVxConsole() 1
+#else
+#define HasVxConsole() 0
+#endif
+
+//-----------------------------------------------------------------------------
+// Set up platform type defines.
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_X360 ) || defined( _PS3 )
+ #ifndef _GAMECONSOLE
+ #define _GAMECONSOLE
+ #endif
+ #define IsPC() 0
+ #define IsGameConsole() 1
+#else
+ #define IsPC() 1
+ #define IsGameConsole() 0
+#endif
+
+
+
+//-----------------------------------------------------------------------------
+// Set up build configuration defines.
+//-----------------------------------------------------------------------------
+#ifdef _CERT
+#define IsCert() 1
+#else
+#define IsCert() 0
+#endif
+
+#ifdef _DEBUG
+#define IsRelease() 0
+#define IsDebug() 1
+#else
+#define IsRelease() 1
+#define IsDebug() 0
+#endif
+
+#ifdef _RETAIL
+#define IsRetail() 1
+#else
+#define IsRetail() 0
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Portable data types
+//-----------------------------------------------------------------------------
+typedef unsigned char uint8;
+typedef signed char int8;
+
+#if defined( COMPILER_MSVC )
+
+ typedef __int16 int16;
+ typedef unsigned __int16 uint16;
+ typedef __int32 int32;
+ typedef unsigned __int32 uint32;
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+
+ // intp is an integer that can accomodate a pointer
+ // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
+ typedef intptr_t intp;
+ typedef uintptr_t uintp;
+
+ #if defined( COMPILER_MSVCX360 )
+ #ifdef __m128
+ #undef __m128
+ #endif
+ #define __m128 __vector4
+ #endif
+
+#else // !COMPILER_MSVC
+
+ typedef short int16;
+ typedef unsigned short uint16;
+ typedef int int32;
+ typedef unsigned int uint32;
+ typedef long long int64;
+ typedef unsigned long long uint64;
+ #ifdef PLATFORM_64BITS
+ typedef long long intp;
+ typedef unsigned long long uintp;
+ #else
+ typedef int intp;
+ typedef unsigned int uintp;
+ #endif
+ typedef void *HWND;
+#endif // else COMPILER_MSVC
+
+#if defined(_PS3) && !defined(NO_SIMD)
+typedef union __attribute__ ((aligned (16)))
+{
+ float m128_f32[4];
+} l_m128;
+
+typedef __vector float __vector4;
+typedef __vector4 __m128;
+
+const __m128 VMX_ZERO=(vector float)(0.0f);
+const __m128 VMX_ONE_HALF=(vector float)(0.5f);
+const __m128 VMX_ONE=(vector float)(1.0f);
+
+// Syntaxic sugar for multiply
+inline __attribute__ ((always_inline)) __m128 __vec_mul(const __m128 a, const __m128 b)
+{
+ return vec_madd(a,b,VMX_ZERO);
+}
+
+// Refined reciprocal function
+inline __attribute__ ((always_inline)) __m128 __vec_rec(const __m128 a)
+{
+ //Get the reciprocal estimate
+ vector float estimate = vec_re( a );
+
+ //One round of Newton-Raphson refinement
+ return vec_madd( vec_nmsub( estimate, a, VMX_ONE ), estimate, estimate );
+}
+
+// refined reciprocal square root
+inline __attribute__ ((always_inline)) __m128 __vec_rsqrt(const __m128 a)
+{
+ //Get the square root reciprocal estimate
+ __m128 estimate = vec_rsqrte( a );
+
+ //One round of Newton-Raphson refinement
+ __m128 estimateSquared = __vec_mul( estimate, estimate);
+ __m128 halfEstimate = __vec_mul( estimate, VMX_ONE_HALF);
+ return vec_madd( vec_nmsub( a, estimateSquared, VMX_ONE ), halfEstimate, estimate );
+}
+
+// refined square root
+inline __attribute__ ((always_inline)) __m128 __vec_sqrt(const __m128 a)
+{
+ return __vec_mul( a, __vec_rsqrt( a ));
+}
+
+// estimate square root
+inline __attribute__ ((always_inline)) __m128 __vec_sqrtest(const __m128 a)
+{
+ return __vec_mul( a, vec_rsqrte( a ));
+}
+
+// Syntaxic sugar for multiply
+inline __attribute__ ((always_inline)) __m128 __vec_div(const __m128 a, const __m128 b)
+{
+ return __vec_mul( a, __vec_rec( b ));
+}
+
+// load an unaligned array of float in a vector of floats
+inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned(const float* in)
+{
+ return vec_perm(vec_ld(0,in),
+ vec_ld(sizeof(__m128),in),
+ vec_lvsl( 0, in ));
+}
+
+// load an unaligned array of 3 floats in a vector of floats, last member being 0.
+inline __attribute__ ((always_inline)) __m128 __vec_ld_unaligned3(const float* in)
+{
+ return vec_and(__vec_ld_unaligned(in),(__m128)(vector unsigned int)(0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF ,0));
+}
+
+// stores a vector of floats in an unaligned array of float
+inline __attribute__ ((always_inline)) void __vec_st_unaligned(__m128 in, float* out)
+{
+ __m128 temp0 = vec_ld(0,out);
+ __m128 temp1 = vec_ld(16,out);
+ vector unsigned char align = vec_lvsr(0,out);
+ vector unsigned char mask = vec_perm ((vector unsigned char)(0), (vector unsigned char)(0xFF), align);
+
+ in = vec_perm ( in, in, align);
+ temp0 = vec_sel ( temp0, in, (vector bool)mask);
+ temp1 = vec_sel ( in, temp1, (vector bool)mask);
+ vec_st ( temp0, 0, out);
+ vec_st ( temp1, 16, out);
+}
+
+// stores x,y,z from a vector of floats in an unaligned array of 3 floats
+inline __attribute__ ((always_inline)) void __vec_st_unaligned3(__m128 in, float* out)
+{
+ __m128 temp0 = vec_ld(0,out);
+ __m128 temp1 = vec_ld(16,out);
+ vector unsigned char align = vec_lvsr(0,out);
+ vector unsigned char mask = vec_perm ((vector unsigned char)(0),
+ (vector unsigned char)(0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0,0,0,0),
+ align);
+
+ in = vec_perm ( in, in, align);
+ temp0 = vec_sel ( temp0, in, (vector bool)mask);
+ temp1 = vec_sel ( in, temp1, (vector bool)mask);
+ vec_st ( temp0, 0, out);
+ vec_st ( temp1, 16, out);
+}
+
+#endif // defined(NO_SIMD)
+
+
+typedef float float32;
+typedef double float64;
+
+// for when we don't care about how many bits we use
+typedef unsigned int uint;
+
+#ifdef PLATFORM_POSIX
+#ifndef _PS3
+typedef unsigned int DWORD;
+typedef unsigned int *LPDWORD;
+#endif
+typedef unsigned short WORD;
+typedef void * HINSTANCE;
+#define _MAX_PATH PATH_MAX
+#endif
+
+// MSVC CRT uses 0x7fff while gcc uses MAX_INT, leading to mismatches between platforms
+// As a result, we pick the least common denominator here. This should be used anywhere
+// you might typically want to use RAND_MAX
+#define VALVE_RAND_MAX 0x7fff
+// Maximum and minimum representable values
+#ifndef PLATFORM_OSX
+
+#define INT8_MAX SCHAR_MAX
+#define INT16_MAX SHRT_MAX
+#define INT32_MAX LONG_MAX
+#define INT64_MAX (((int64)~0) >> 1)
+
+#define INT8_MIN SCHAR_MIN
+#define INT16_MIN SHRT_MIN
+#define INT32_MIN LONG_MIN
+#define INT64_MIN (((int64)1) << 63)
+
+#define UINT8_MAX ((uint8)~0)
+#define UINT16_MAX ((uint16)~0)
+#define UINT32_MAX ((uint32)~0)
+#define UINT64_MAX ((uint64)~0)
+
+#define UINT8_MIN 0
+#define UINT16_MIN 0
+#define UINT32_MIN 0
+#define UINT64_MIN 0
+
+#endif // PLATFORM_OSX
+
+#ifndef UINT_MIN
+#define UINT_MIN UINT32_MIN
+#endif
+
+#define FLOAT32_MAX FLT_MAX
+#define FLOAT64_MAX DBL_MAX
+
+#ifdef GNUC
+#undef offsetof
+// Note: can't use builtin offsetof because many use cases (esp. in templates) wouldn't compile due to restrictions on the builtin offsetof
+//#define offsetof( type, var ) __builtin_offsetof( type, var )
+#define offsetof(s,m) ( (size_t)&(((s *)0x1000000)->m) - 0x1000000u )
+#else
+#include <stddef.h>
+#undef offsetof
+#define offsetof(s,m) (size_t)&(((s *)0)->m)
+#endif
+
+
+#define FLOAT32_MIN FLT_MIN
+#define FLOAT64_MIN DBL_MIN
+
+//-----------------------------------------------------------------------------
+// Long is evil because it's treated differently by different compilers
+// Preventing its use is nasty however. This #define, which should be
+// turned on in individual VPC files, causes you to include tier0/valve_off.h
+// before standard C + windows headers, and include tier0/valve_on.h after
+// standard C + windows headers. So, there's some painful overhead to disabling long
+//-----------------------------------------------------------------------------
+#ifdef DISALLOW_USE_OF_LONG
+ #define long long_is_the_devil_stop_using_it_use_int32_or_int64
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Various compiler-specific keywords
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC
+
+ #ifdef FORCEINLINE
+ #undef FORCEINLINE
+ #endif
+ #define STDCALL __stdcall
+ #ifndef FASTCALL
+ #define FASTCALL __fastcall
+ #endif
+ #define FORCEINLINE __forceinline
+ #define FORCEINLINE_TEMPLATE __forceinline
+ #define NULLTERMINATED __nullterminated
+
+ // This can be used to ensure the size of pointers to members when declaring
+ // a pointer type for a class that has only been forward declared
+ #define SINGLE_INHERITANCE __single_inheritance
+ #define MULTIPLE_INHERITANCE __multiple_inheritance
+ #define EXPLICIT explicit
+ #define NO_VTABLE __declspec( novtable )
+
+ // gcc doesn't allow storage specifiers on explicit template instatiation, but visual studio needs them to avoid link errors.
+ #define TEMPLATE_STATIC static
+
+ // Used for dll exporting and importing
+ #define DLL_EXPORT extern "C" __declspec( dllexport )
+ #define DLL_IMPORT extern "C" __declspec( dllimport )
+
+ // Can't use extern "C" when DLL exporting a class
+ #define DLL_CLASS_EXPORT __declspec( dllexport )
+ #define DLL_CLASS_IMPORT __declspec( dllimport )
+
+ // Can't use extern "C" when DLL exporting a global
+ #define DLL_GLOBAL_EXPORT extern __declspec( dllexport )
+ #define DLL_GLOBAL_IMPORT extern __declspec( dllimport )
+
+ // Pass hints to the compiler to prevent it from generating unnessecary / stupid code
+ // in certain situations. Several compilers other than MSVC also have an equivilent
+ // construct.
+ //
+ // Essentially the 'Hint' is that the condition specified is assumed to be true at
+ // that point in the compilation. If '0' is passed, then the compiler assumes that
+ // any subsequent code in the same 'basic block' is unreachable, and thus usually
+ // removed.
+ #define HINT(THE_HINT) __assume((THE_HINT))
+
+ // decls for aligning data
+ #define DECL_ALIGN(x) __declspec( align( x ) )
+
+ // GCC had a few areas where it didn't construct objects in the same order
+ // that Windows does. So when CVProfile::CVProfile() would access g_pMemAlloc,
+ // it would crash because the allocator wasn't initalized yet.
+ #define CONSTRUCT_EARLY
+
+ #define SELECTANY __declspec(selectany)
+
+ #define RESTRICT __restrict
+ #define RESTRICT_FUNC __declspec(restrict)
+ #define FMTFUNCTION( a, b )
+ #define NOINLINE
+
+#if !defined( NO_THREAD_LOCAL )
+ #define DECL_THREAD_LOCAL __declspec(thread)
+#endif
+
+ #define DISABLE_VC_WARNING( x ) __pragma(warning(disable:4310) )
+ #define DEFAULT_VC_WARNING( x ) __pragma(warning(default:4310) )
+
+
+#elif defined ( COMPILER_GCC ) || defined( COMPILER_SNC )
+
+ #if defined( COMPILER_SNC )
+ #define STDCALL
+ #define __stdcall
+ #elif (CROSS_PLATFORM_VERSION >= 1) && !defined( PLATFORM_64BITS ) && !defined( COMPILER_PS3 )
+ #define STDCALL __attribute__ ((__stdcall__))
+ #else
+ #define STDCALL
+ #define __stdcall __attribute__ ((__stdcall__))
+ #endif
+
+ #define FASTCALL
+ #ifdef _LINUX_DEBUGGABLE
+ #define FORCEINLINE
+ #else
+ #ifdef _PS3
+ // [IESTYN 7/29/2010] As of SDK 3.4.0, this causes bad code generation in NET_Tick::ReadFromBuffer in netmessages.cpp,
+ // which caused (seeming) random network packet corruption. It probably causes other bugs too.
+ #define FORCEINLINE inline /* __attribute__ ((always_inline)) */
+ #else
+ #define FORCEINLINE inline __attribute__ ((always_inline))
+ #endif
+ #endif
+
+ // GCC 3.4.1 has a bug in supporting forced inline of templated functions
+ // this macro lets us not force inlining in that case
+ #define FORCEINLINE_TEMPLATE inline
+ #define SINGLE_INHERITANCE
+ #define MULTIPLE_INHERITANCE
+ #define EXPLICIT
+ #define NO_VTABLE
+
+ #define NULLTERMINATED
+
+#if defined( COMPILER_SNC )
+ #define TEMPLATE_STATIC static
+#else
+ #define TEMPLATE_STATIC
+#endif
+
+ // Used for dll exporting and importing
+ #ifdef COMPILER_SNC
+ #define DLL_DECLARATION_DEFAULT_VISIBILITY
+ #else
+ #define DLL_DECLARATION_DEFAULT_VISIBILITY __attribute__ ((visibility("default")))
+ #endif
+ #define DLL_EXPORT extern "C" DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_IMPORT extern "C"
+
+ // Can't use extern "C" when DLL exporting a class
+#ifndef _PS3
+ #define __stdcall __attribute__ ((__stdcall__))
+#endif
+ #define DLL_CLASS_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_CLASS_IMPORT
+
+ // Can't use extern "C" when DLL exporting a global
+ #define DLL_GLOBAL_EXPORT DLL_DECLARATION_DEFAULT_VISIBILITY
+ #define DLL_GLOBAL_IMPORT extern
+
+ #define HINT(THE_HINT) __builtin_expect( THE_HINT, 1 )
+ #define DECL_ALIGN(x) __attribute__( ( aligned( x ) ) )
+ #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
+ #define SELECTANY __attribute__((weak))
+ #define RESTRICT __restrict__
+ #define RESTRICT_FUNC RESTRICT_FUNC_NOT_YET_DEFINED_FOR_THIS_COMPILER
+ #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( printf, fmtargnumber, firstvarargnumber )))
+ #define NOINLINE __attribute__ ((noinline))
+
+#if !defined( NO_THREAD_LOCAL )
+ #define DECL_THREAD_LOCAL __thread
+#endif
+
+ #define DISABLE_VC_WARNING( x )
+ #define DEFAULT_VC_WARNING( x )
+
+#else
+
+ #define DECL_ALIGN(x) /* */
+ #define SELECTANY static
+
+#endif
+
+#if defined( GNUC ) && !defined( COMPILER_PS3 ) // use pre-align on PS3
+// gnuc has the align decoration at the end
+#define ALIGN4
+#define ALIGN8
+#define ALIGN16
+#define ALIGN32
+#define ALIGN128
+
+#undef ALIGN16_POST
+#define ALIGN4_POST DECL_ALIGN(4)
+#define ALIGN8_POST DECL_ALIGN(8)
+#define ALIGN16_POST DECL_ALIGN(16)
+#define ALIGN32_POST DECL_ALIGN(32)
+#define ALIGN128_POST DECL_ALIGN(128)
+#else
+// MSVC has the align at the start of the struct
+// PS3 SNC supports both
+#define ALIGN4 DECL_ALIGN(4)
+#define ALIGN8 DECL_ALIGN(8)
+#define ALIGN16 DECL_ALIGN(16)
+#define ALIGN32 DECL_ALIGN(32)
+#define ALIGN128 DECL_ALIGN(128)
+
+#define ALIGN4_POST
+#define ALIGN8_POST
+#define ALIGN16_POST
+#define ALIGN32_POST
+#define ALIGN128_POST
+#endif
+
+// This can be used to declare an abstract (interface only) class.
+// Classes marked abstract should not be instantiated. If they are, and access violation will occur.
+//
+// Example of use:
+//
+// abstract_class CFoo
+// {
+// ...
+// }
+//
+// MSDN __declspec(novtable) documentation: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclang/html/_langref_novtable.asp
+//
+// Note: NJS: This is not enabled for regular PC, due to not knowing the implications of exporting a class with no no vtable.
+// It's probable that this shouldn't be an issue, but an experiment should be done to verify this.
+//
+#ifndef COMPILER_MSVCX360
+ #define abstract_class class
+#else
+ #define abstract_class class NO_VTABLE
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Why do we need this? It would be nice to make it die die die
+//-----------------------------------------------------------------------------
+// Alloca defined for this platform
+#if defined( COMPILER_MSVC ) && !defined( WINDED )
+ #if defined(_M_IX86)
+ #define __i386__ 1
+ #endif
+#endif
+
+#if defined __i386__ && !defined __linux__
+ #define id386 1
+#else
+ #define id386 0
+#endif // __i386__
+
+
+//-----------------------------------------------------------------------------
+// Disable annoying unhelpful warnings
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC
+// Remove warnings from warning level 4.
+#pragma warning(disable : 4514) // warning C4514: 'acosl' : unreferenced inline function has been removed
+#pragma warning(disable : 4100) // warning C4100: 'hwnd' : unreferenced formal parameter
+#pragma warning(disable : 4127) // warning C4127: conditional expression is constant
+#pragma warning(disable : 4512) // warning C4512: 'InFileRIFF' : assignment operator could not be generated
+#pragma warning(disable : 4611) // warning C4611: interaction between '_setjmp' and C++ object destruction is non-portable
+#pragma warning(disable : 4710) // warning C4710: function 'x' not inlined
+#pragma warning(disable : 4702) // warning C4702: unreachable code
+#pragma warning(disable : 4505) // unreferenced local function has been removed
+#pragma warning(disable : 4239) // nonstandard extension used : 'argument' ( conversion from class Vector to class Vector& )
+#pragma warning(disable : 4097) // typedef-name 'BaseClass' used as synonym for class-name 'CFlexCycler::CBaseFlex'
+#pragma warning(disable : 4324) // Padding was added at the end of a structure
+#pragma warning(disable : 4244) // type conversion warning.
+#pragma warning(disable : 4305) // truncation from 'const double ' to 'float '
+#pragma warning(disable : 4786) // Disable warnings about long symbol names
+#pragma warning(disable : 4250) // 'X' : inherits 'Y::Z' via dominance
+#pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union
+
+#if _MSC_VER >= 1300
+#pragma warning(disable : 4511) // Disable warnings about private copy constructors
+#pragma warning(disable : 4121) // warning C4121: 'symbol' : alignment of a member was sensitive to packing
+#pragma warning(disable : 4530) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc (disabled due to std headers having exception syntax)
+#endif
+
+#if _MSC_VER >= 1400
+#pragma warning(disable : 4996) // functions declared deprecated
+#endif
+
+// When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
+#if !defined( COMPILER_MSVC64 )
+#if ( CROSS_PLATFORM_VERSION < 1 )
+#pragma warning( disable : 4267 ) // conversion from 'size_t' to 'int', possible loss of data
+#pragma warning( disable : 4311 ) // pointer truncation from 'char *' to 'int'
+#pragma warning( disable : 4312 ) // conversion from 'unsigned int' to 'memhandle_t' of greater size
+#endif
+#endif
+
+#elif defined( COMPILER_SNC )
+#pragma diag_suppress=1700 // warning 1700: class "%s" has virtual functions but non-virtual destructor
+// Uncomment the following line if you want to investigate a specific compiler remark without all the noise:
+// #pragma diag_suppress=1700, 83, 162, 182, 192, 194, 229, 238, 262, 341, 382, 401, 402, 403, 481, 817, 828, 833, 1363, 1771, 1774, 1779, 1780, 1783, 1785, 1786, 1788
+#endif
+
+// Pull in the /analyze code annotations.
+#include "annotations.h"
+
+//-----------------------------------------------------------------------------
+// Convert int<-->pointer, avoiding 32/64-bit compiler warnings:
+//-----------------------------------------------------------------------------
+#define INT_TO_POINTER( i ) (void *)( ( i ) + (char *)NULL )
+#define POINTER_TO_INT( p ) ( (int)(uint64)( p ) )
+
+
+//-----------------------------------------------------------------------------
+// Stack-based allocation related helpers
+//-----------------------------------------------------------------------------
+#if defined( COMPILER_GCC ) || defined( COMPILER_SNC )
+
+ #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
+
+ #ifdef PLATFORM_OSX
+ #define mallocsize( _p ) ( malloc_size( _p ) )
+ #else
+ #define mallocsize( _p ) ( malloc_usable_size( _p ) )
+ #endif
+
+#elif defined ( COMPILER_MSVC )
+
+ #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
+ #define mallocsize( _p ) ( _msize( _p ) )
+
+#endif
+
+#define stackfree( _p ) 0
+
+//-----------------------------------------------------------------------------
+// Used to break into the debugger
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_MSVC64
+ #define DebuggerBreak() __debugbreak()
+#elif COMPILER_MSVC32
+ #define DebuggerBreak() __asm { int 3 }
+#elif COMPILER_MSVCX360
+ #define DebuggerBreak() DebugBreak()
+#elif COMPILER_GCC
+ #if defined( _PS3 )
+ #define DebuggerBreak() { __asm volatile ("tw 31,1,1"); }
+ #elif defined( OSX )
+ #define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm__ __volatile__ ( "int $3" ); } else { raise(SIGTRAP); }
+ #elif defined( PLATFORM_CYGWIN ) || defined( PLATFORM_POSIX )
+ #define DebuggerBreak() __asm__( "int $0x3;")
+ #else
+ #define DebuggerBreak() asm( "int3" )
+ #endif
+#elif defined( COMPILER_SNC ) && defined( COMPILER_PS3 )
+static bool sPS3_SuppressAssertsInThisFile = false; // you can throw this in the debugger to temporarily disable asserts inside any particular .cpp module.
+ #define DebuggerBreak() if (!sPS3_SuppressAssertsInThisFile) __builtin_snpause(); // <sergiy> from SNC Migration Guide, tw 31,1,1
+#else
+#error DebuggerBreak() is not defined for this platform!
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+ #if defined( fsel )
+ #error
+ #endif
+#else
+
+FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+
+#endif
+
+//-----------------------------------------------------------------------------
+// DLL export for platform utilities
+//-----------------------------------------------------------------------------
+#ifndef STATIC_TIER0
+
+#ifdef TIER0_DLL_EXPORT
+#define PLATFORM_INTERFACE DLL_EXPORT
+#define PLATFORM_OVERLOAD DLL_GLOBAL_EXPORT
+#define PLATFORM_CLASS DLL_CLASS_EXPORT
+#else
+#define PLATFORM_INTERFACE DLL_IMPORT
+#define PLATFORM_OVERLOAD DLL_GLOBAL_IMPORT
+#define PLATFORM_CLASS DLL_CLASS_IMPORT
+#endif
+
+#else // BUILD_AS_DLL
+
+#define PLATFORM_INTERFACE extern
+#define PLATFORM_OVERLOAD
+#define PLATFORM_CLASS
+
+#endif // BUILD_AS_DLL
+
+
+//-----------------------------------------------------------------------------
+// Returns true if debugger attached, false otherwise
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS ) || defined( _PS3 )
+PLATFORM_INTERFACE void Plat_DebugString( const tchar * );
+#else
+#define Plat_DebugString(s) ((void)0)
+#endif
+
+PLATFORM_INTERFACE bool Plat_IsInDebugSession();
+
+#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
+
+
+//-----------------------------------------------------------------------------
+// Message Box
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS_PC )
+PLATFORM_INTERFACE void Plat_MessageBox( const char *pTitle, const tchar *pMessage );
+#else
+#define Plat_MessageBox( t, m ) ((void)0)
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Posix platform helpers
+//-----------------------------------------------------------------------------
+#ifdef PLATFORM_POSIX
+
+// Visual Studio likes to put an underscore in front of anything that looks like a portable function.
+#define _strupr strupr
+#define _getcwd getcwd
+#define _open open
+#define _lseek lseek
+#define _read read
+#define _close close
+#define _vsnprintf vsnprintf
+#define _stat stat
+#define _O_RDONLY O_RDONLY
+#define _stricmp strcasecmp
+#define _finite finite
+#define _unlink unlink
+#define _putenv putenv
+#define _chdir chdir
+#define _access access
+
+#define strcmpi stricmp
+#define stricmp strcasecmp
+#define _alloca alloca
+#define GetProcAddress dlsym
+#define _chdir chdir
+#ifndef _PS3
+#define _strnicmp strnicmp
+#endif
+#define strnicmp strncasecmp
+#define _snwprintf swprintf
+#define swprintf_s swprintf
+#define wcsicmp _wcsicmp
+#define _wcsicmp wcscmp
+#define _tempnam tempnam
+#define strtok_s strtok_r
+#define _mkdir(dir) mkdir( dir, S_IRWXU | S_IRWXG | S_IRWXO )
+#define _wtoi(arg) wcstol(arg, NULL, 10)
+#define _wtoi64(arg) wcstoll(arg, NULL, 10)
+
+#ifndef _PS3
+typedef uint32 HMODULE;
+#endif
+typedef void *HANDLE;
+#define __cdecl
+
+#if !defined( _snprintf ) // some vpc's define this on the command line
+#define _snprintf snprintf
+#endif
+
+#include <alloca.h>
+#include <unistd.h> // get unlink
+#include <errno.h>
+
+#endif // PLATFORM_POSIX
+
+#ifdef PLATFORM_WINDOWS
+#ifndef SOCKLEN_T
+#define SOCKLEN_T
+typedef int socklen_t;
+#endif
+#endif
+
+//-----------------------------------------------------------------------------
+// Generally useful platform-independent macros (move to another file?)
+//-----------------------------------------------------------------------------
+
+// need macro for constant expression
+#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) )
+
+// Force a function call site -not- to inlined. (useful for profiling)
+#define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
+
+// Marks the codepath from here until the next branch entry point as unreachable,
+// and asserts if any attempt is made to execute it.
+#define UNREACHABLE() { Assert(0); HINT(0); }
+
+// In cases where no default is present or appropriate, this causes MSVC to generate
+// as little code as possible, and throw an assertion in debug.
+#define NO_DEFAULT default: UNREACHABLE();
+
+// Defines MAX_PATH
+#ifndef MAX_PATH
+ #define MAX_PATH 260
+#endif
+
+
+//-----------------------------------------------------------------------------
+// FP exception handling
+//-----------------------------------------------------------------------------
+//#define CHECK_FLOAT_EXCEPTIONS 1
+//#define CHECK_FPU_CONTROL_WORD_SET 1 // x360 only
+
+#if defined( COMPILER_MSVC64 )
+
+ inline void SetupFPUControlWord()
+ {
+ }
+
+#elif defined ( COMPILER_MSVC32 )
+
+ inline void SetupFPUControlWordForceExceptions()
+ {
+ // use local to get and store control word
+ uint16 tmpCtrlW;
+ __asm
+ {
+ fnclex /* clear all current exceptions */
+ fnstcw word ptr [tmpCtrlW] /* get current control word */
+ and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
+ or [tmpCtrlW], 0230h /* set to 53-bit, mask only inexact, underflow */
+ fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
+ }
+ }
+
+ #ifdef CHECK_FLOAT_EXCEPTIONS
+
+ inline void SetupFPUControlWord()
+ {
+ SetupFPUControlWordForceExceptions();
+ }
+
+ #else
+
+ inline void SetupFPUControlWord()
+ {
+ // use local to get and store control word
+ uint16 tmpCtrlW;
+ __asm
+ {
+ fnstcw word ptr [tmpCtrlW] /* get current control word */
+ and [tmpCtrlW], 0FCC0h /* Keep infinity control + rounding control */
+ or [tmpCtrlW], 023Fh /* set to 53-bit, mask only inexact, underflow */
+ fldcw word ptr [tmpCtrlW] /* put new control word in FPU */
+ }
+ }
+
+ #endif
+
+#elif defined ( COMPILER_GCC )
+
+// Works for PS3
+ inline void SetupFPUControlWord()
+ {
+#ifdef _PS3
+// TODO: PS3 compiler spits out the following errors:
+// C:/tmp/ccIN0aaa.s: Assembler messages:
+// C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
+// C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
+#else
+ __volatile unsigned short int __cw;
+ __asm __volatile ("fnstcw %0" : "=m" (__cw));
+ __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
+ __cw = __cw | 0x023F; // set 53-bit, no exceptions
+ __asm __volatile ("fldcw %0" : : "m" (__cw));
+#endif
+ }
+
+#elif defined ( COMPILER_SNC )
+
+// Works for PS3
+ inline void SetupFPUControlWord()
+ {
+#ifdef _PS3
+// TODO: PS3 compiler spits out the following errors:
+// C:/tmp/ccIN0aaa.s: Assembler messages:
+// C:/tmp/ccIN0aaa.s(80): Error: Unrecognized opcode: `fnstcw'
+// C:/tmp/ccIN0aaa.s(93): Error: Unrecognized opcode: `fldcw'
+#else
+ __volatile unsigned short int __cw;
+ __asm __volatile ("fnstcw %0" : "=m" (__cw));
+ __cw = __cw & 0x0FCC0; // keep infinity control, keep rounding mode
+ __cw = __cw | 0x023F; // set 53-bit, no exceptions
+ __asm __volatile ("fldcw %0" : : "m" (__cw));
+#endif
+ }
+
+#elif defined( COMPILER_MSVCX360 )
+
+ #ifdef CHECK_FPU_CONTROL_WORD_SET
+ FORCEINLINE bool IsFPUControlWordSet()
+ {
+ float f = 0.996f;
+ union
+ {
+ double flResult;
+ int pResult[2];
+ };
+ flResult = __fctiw( f );
+ return ( pResult[1] == 1 );
+ }
+ #else
+ #define IsFPUControlWordSet() 1
+ #endif
+
+ inline void SetupFPUControlWord()
+ {
+ // Set round-to-nearest in FPSCR
+ // (cannot assemble, must use op-code form)
+ __emit( 0xFF80010C ); // mtfsfi 7,0
+
+ // Favour compatibility over speed (make sure the VPU set to Java-compliant mode)
+ // NOTE: the VPU *always* uses round-to-nearest
+ __vector4 a = { 0.0f, 0.0f, 0.0f, 0.0f };
+ a; // Avoid compiler warning
+ __asm
+ {
+ mtvscr a; // Clear the Vector Status & Control Register to zero
+ }
+ }
+
+#endif // COMPILER_MSVCX360
+
+
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Standard functions for handling endian-ness
+//-----------------------------------------------------------------------------
+
+//-------------------------------------
+// Basic swaps
+//-------------------------------------
+
+template <typename T>
+inline T WordSwapC( T w )
+{
+ uint16 temp;
+
+ temp = ((*((uint16 *)&w) & 0xff00) >> 8);
+ temp |= ((*((uint16 *)&w) & 0x00ff) << 8);
+
+ return *((T*)&temp);
+}
+
+template <typename T>
+inline T DWordSwapC( T dw )
+{
+ uint32 temp;
+
+ temp = *((uint32 *)&dw) >> 24;
+ temp |= ((*((uint32 *)&dw) & 0x00FF0000) >> 8);
+ temp |= ((*((uint32 *)&dw) & 0x0000FF00) << 8);
+ temp |= ((*((uint32 *)&dw) & 0x000000FF) << 24);
+
+ return *((T*)&temp);
+}
+
+//-------------------------------------
+// Fast swaps
+//-------------------------------------
+
+#if defined( COMPILER_MSVCX360 )
+
+ #define WordSwap WordSwap360Intr
+ #define DWordSwap DWordSwap360Intr
+
+ template <typename T>
+ inline T WordSwap360Intr( T w )
+ {
+ T output;
+ __storeshortbytereverse( w, 0, &output );
+ return output;
+ }
+
+ template <typename T>
+ inline T DWordSwap360Intr( T dw )
+ {
+ T output;
+ __storewordbytereverse( dw, 0, &output );
+ return output;
+ }
+
+#elif defined( COMPILER_MSVC32 )
+
+ #define WordSwap WordSwapAsm
+ #define DWordSwap DWordSwapAsm
+
+ #pragma warning(push)
+ #pragma warning (disable:4035) // no return value
+
+ template <typename T>
+ inline T WordSwapAsm( T w )
+ {
+ __asm
+ {
+ mov ax, w
+ xchg al, ah
+ }
+ }
+
+ template <typename T>
+ inline T DWordSwapAsm( T dw )
+ {
+ __asm
+ {
+ mov eax, dw
+ bswap eax
+ }
+ }
+
+ #pragma warning(pop)
+
+#else
+
+ #define WordSwap WordSwapC
+ #define DWordSwap DWordSwapC
+
+#endif
+
+//-------------------------------------
+// The typically used methods.
+//-------------------------------------
+
+#if defined( _SGI_SOURCE ) || defined( PLATFORM_X360 ) || defined( _PS3 )
+#define PLAT_BIG_ENDIAN 1
+#else
+#define PLAT_LITTLE_ENDIAN 1
+#endif
+
+
+// If a swapped float passes through the fpu, the bytes may get changed.
+// Prevent this by swapping floats as DWORDs.
+#define SafeSwapFloat( pOut, pIn ) (*((uint*)pOut) = DWordSwap( *((uint*)pIn) ))
+
+#if defined(PLAT_LITTLE_ENDIAN)
+#define BigShort( val ) WordSwap( val )
+#define BigWord( val ) WordSwap( val )
+#define BigLong( val ) DWordSwap( val )
+#define BigDWord( val ) DWordSwap( val )
+#define LittleShort( val ) ( val )
+#define LittleWord( val ) ( val )
+#define LittleLong( val ) ( val )
+#define LittleDWord( val ) ( val )
+#define SwapShort( val ) BigShort( val )
+#define SwapWord( val ) BigWord( val )
+#define SwapLong( val ) BigLong( val )
+#define SwapDWord( val ) BigDWord( val )
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+#define BigFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
+#define LittleFloat( pOut, pIn ) ( *pOut = *pIn )
+#define SwapFloat( pOut, pIn ) BigFloat( pOut, pIn )
+
+#elif defined(PLAT_BIG_ENDIAN)
+
+#define BigShort( val ) ( val )
+#define BigWord( val ) ( val )
+#define BigLong( val ) ( val )
+#define BigDWord( val ) ( val )
+#define LittleShort( val ) WordSwap( val )
+#define LittleWord( val ) WordSwap( val )
+#define LittleLong( val ) DWordSwap( val )
+#define LittleDWord( val ) DWordSwap( val )
+#define SwapShort( val ) LittleShort( val )
+#define SwapWord( val ) LittleWord( val )
+#define SwapLong( val ) LittleLong( val )
+#define SwapDWord( val ) LittleDWord( val )
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+#define BigFloat( pOut, pIn ) ( *pOut = *pIn )
+#define LittleFloat( pOut, pIn ) SafeSwapFloat( pOut, pIn )
+#define SwapFloat( pOut, pIn ) LittleFloat( pOut, pIn )
+
+#else
+
+// @Note (toml 05-02-02): this technique expects the compiler to
+// optimize the expression and eliminate the other path. On any new
+// platform/compiler this should be tested.
+inline short BigShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
+inline uint16 BigWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? WordSwap( val ) : val; }
+inline long BigLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
+inline uint32 BigDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? DWordSwap( val ) : val; }
+inline short LittleShort( short val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
+inline uint16 LittleWord( uint16 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : WordSwap( val ); }
+inline long LittleLong( long val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
+inline uint32 LittleDWord( uint32 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : DWordSwap( val ); }
+inline short SwapShort( short val ) { return WordSwap( val ); }
+inline uint16 SwapWord( uint16 val ) { return WordSwap( val ); }
+inline long SwapLong( long val ) { return DWordSwap( val ); }
+inline uint32 SwapDWord( uint32 val ) { return DWordSwap( val ); }
+
+// Pass floats by pointer for swapping to avoid truncation in the fpu
+inline void BigFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? SafeSwapFloat( pOut, pIn ) : ( *pOut = *pIn ); }
+inline void LittleFloat( float *pOut, const float *pIn ) { int test = 1; ( *(char *)&test == 1 ) ? ( *pOut = *pIn ) : SafeSwapFloat( pOut, pIn ); }
+inline void SwapFloat( float *pOut, const float *pIn ) { SafeSwapFloat( pOut, pIn ); }
+
+#endif
+
+#if PLAT_BIG_ENDIAN
+ #if defined( _PS3 )
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return __lwbrx( base + dwordIndex );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ __stwbrx( base + dwordIndex, dword );
+ }
+ inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
+ {
+ return __ldbrx( base + nWordIndex );
+ }
+
+ inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
+ {
+ __stdbrx( base + nWordIndex, nWord );
+ }
+ #else
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return __loadwordbytereverse( dwordIndex<<2, base );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ __storewordbytereverse( dword, dwordIndex<<2, base );
+ }
+ inline uint64 LoadLittleInt64( uint64 *base, unsigned int nWordIndex )
+ {
+ return __loaddoublewordbytereverse( nWordIndex<<2, base );
+ }
+
+ inline void StoreLittleInt64( uint64 *base, unsigned int nWordIndex, uint64 nWord )
+ {
+ __storedoublewordbytereverse( nWord, nWordIndex<<2, base );
+ }
+ #endif
+#else
+ inline uint32 LoadLittleDWord( uint32 *base, unsigned int dwordIndex )
+ {
+ return LittleDWord( base[dwordIndex] );
+ }
+
+ inline void StoreLittleDWord( uint32 *base, unsigned int dwordIndex, uint32 dword )
+ {
+ base[dwordIndex] = LittleDWord(dword);
+ }
+#endif
+
+
+// When in benchmark mode, the timer returns a simple incremented value each time you call it.
+//
+// It should not be changed after startup unless you really know what you're doing. The only place
+// that should do this is the benchmark code itself so it can output a legit duration.
+PLATFORM_INTERFACE void Plat_SetBenchmarkMode( bool bBenchmarkMode );
+PLATFORM_INTERFACE bool Plat_IsInBenchmarkMode();
+
+
+PLATFORM_INTERFACE double Plat_FloatTime(); // Returns time in seconds since the module was loaded.
+PLATFORM_INTERFACE uint32 Plat_MSTime(); // Time in milliseconds.
+PLATFORM_INTERFACE uint64 Plat_GetClockStart(); // Snapshot of the clock when app started.
+PLATFORM_INTERFACE uint64 Timer_GetTimeUS();
+
+// Get the local calendar time.
+// Same as time() followed by localtime(), but non-crash-prone and threadsafe.
+PLATFORM_INTERFACE void Plat_GetLocalTime( struct tm *pNow );
+
+// Convert a time_t (specified in nTime - seconds since Jan 1, 1970 UTC) to a local calendar time in a threadsafe and non-crash-prone way.
+PLATFORM_INTERFACE void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow );
+
+// Get a time string (same as ascstring, but threadsafe).
+PLATFORM_INTERFACE void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes );
+
+// converts a time_t to a struct tm without the local time conversion of ConvertToLocalTime
+PLATFORM_INTERFACE void Plat_gmtime( uint64 nTime, struct tm *pTime );
+PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
+
+// Get the process' executable filename.
+PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
+
+PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
+
+// b/w compatibility
+#define Sys_FloatTime Plat_FloatTime
+
+// Protect against bad auto operator=
+#define DISALLOW_OPERATOR_EQUAL( _classname ) \
+ private: \
+ _classname &operator=( const _classname & ); \
+ public:
+
+// Define a reasonable operator=
+#define IMPLEMENT_OPERATOR_EQUAL( _classname ) \
+ public: \
+ _classname &operator=( const _classname &src ) \
+ { \
+ memcpy( this, &src, sizeof(_classname) ); \
+ return *this; \
+ }
+
+// Processor Information:
+struct CPUInformation
+{
+ int m_Size; // Size of this structure, for forward compatability.
+
+ bool m_bRDTSC : 1, // Is RDTSC supported?
+ m_bCMOV : 1, // Is CMOV supported?
+ m_bFCMOV : 1, // Is FCMOV supported?
+ m_bSSE : 1, // Is SSE supported?
+ m_bSSE2 : 1, // Is SSE2 Supported?
+ m_b3DNow : 1, // Is 3DNow! Supported?
+ m_bMMX : 1, // Is MMX supported?
+ m_bHT : 1; // Is HyperThreading supported?
+
+ uint8 m_nLogicalProcessors; // Number op logical processors.
+ uint8 m_nPhysicalProcessors; // Number of physical processors
+
+ bool m_bSSE3 : 1,
+ m_bSSSE3 : 1,
+ m_bSSE4a : 1,
+ m_bSSE41 : 1,
+ m_bSSE42 : 1;
+
+ int64 m_Speed; // In cycles per second.
+
+ tchar* m_szProcessorID; // Processor vendor Identification.
+
+ CPUInformation(): m_Size(0){}
+};
+
+PLATFORM_INTERFACE const CPUInformation& GetCPUInformation();
+
+PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
+PLATFORM_INTERFACE void GetCurrentDayOfTheWeek( int *pDay ); // 0 = Sunday
+PLATFORM_INTERFACE void GetCurrentDayOfTheYear( int *pDay ); // 0 = Jan 1
+
+// ---------------------------------------------------------------------------------- //
+// Performance Monitoring Events - L2 stats etc...
+// ---------------------------------------------------------------------------------- //
+PLATFORM_INTERFACE void InitPME();
+PLATFORM_INTERFACE void ShutdownPME();
+
+
+//-----------------------------------------------------------------------------
+// Security related functions
+//-----------------------------------------------------------------------------
+// Ensure that the hardware key's drivers have been installed.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyDriver();
+
+// Ok, so this isn't a very secure way to verify the hardware key for now. It
+// is primarially depending on the fact that all the binaries have been wrapped
+// with the secure wrapper provided by the hardware keys vendor.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKey();
+
+// The same as above, but notifies user with a message box when the key isn't in
+// and gives him an opportunity to correct the situation.
+PLATFORM_INTERFACE bool Plat_VerifyHardwareKeyPrompt();
+
+// Can be called in real time, doesn't perform the verify every frame. Mainly just
+// here to allow the game to drop out quickly when the key is removed, rather than
+// allowing the wrapper to pop up it's own blocking dialog, which the engine doesn't
+// like much.
+PLATFORM_INTERFACE bool Plat_FastVerifyHardwareKey();
+
+//-----------------------------------------------------------------------------
+// Just logs file and line to simple.log
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE void* Plat_SimpleLog( const tchar* file, int line );
+
+
+#if defined( _X360 )
+#define Plat_FastMemset XMemSet
+#define Plat_FastMemcpy XMemCpy
+#else
+#define Plat_FastMemset memset
+#define Plat_FastMemcpy memcpy
+#endif
+
+//-----------------------------------------------------------------------------
+// XBOX Components valid in PC compilation space
+//-----------------------------------------------------------------------------
+
+#define XBOX_DVD_SECTORSIZE 2048
+#define XBOX_DVD_ECC_SIZE 32768 // driver reads in quantum ECC blocks
+#define XBOX_HDD_SECTORSIZE 512
+
+// Custom windows messages for Xbox input
+#define WM_XREMOTECOMMAND (WM_USER + 100)
+#define WM_XCONTROLLER_KEY (WM_USER + 101)
+#define WM_SYS_UI (WM_USER + 102)
+#define WM_SYS_SIGNINCHANGED (WM_USER + 103)
+#define WM_SYS_STORAGEDEVICESCHANGED (WM_USER + 104)
+#define WM_SYS_PROFILESETTINGCHANGED (WM_USER + 105)
+#define WM_SYS_MUTELISTCHANGED (WM_USER + 106)
+#define WM_SYS_INPUTDEVICESCHANGED (WM_USER + 107)
+#define WM_SYS_INPUTDEVICECONFIGCHANGED (WM_USER + 108)
+#define WM_LIVE_CONNECTIONCHANGED (WM_USER + 109)
+#define WM_LIVE_INVITE_ACCEPTED (WM_USER + 110)
+#define WM_LIVE_LINK_STATE_CHANGED (WM_USER + 111)
+#define WM_LIVE_CONTENT_INSTALLED (WM_USER + 112)
+#define WM_LIVE_MEMBERSHIP_PURCHASED (WM_USER + 113)
+#define WM_LIVE_VOICECHAT_AWAY (WM_USER + 114)
+#define WM_LIVE_PRESENCE_CHANGED (WM_USER + 115)
+#define WM_FRIENDS_PRESENCE_CHANGED (WM_USER + 116)
+#define WM_FRIENDS_FRIEND_ADDED (WM_USER + 117)
+#define WM_FRIENDS_FRIEND_REMOVED (WM_USER + 118)
+#define WM_CUSTOM_GAMEBANNERPRESSED (WM_USER + 119)
+#define WM_CUSTOM_ACTIONPRESSED (WM_USER + 120)
+#define WM_XMP_STATECHANGED (WM_USER + 121)
+#define WM_XMP_PLAYBACKBEHAVIORCHANGED (WM_USER + 122)
+#define WM_XMP_PLAYBACKCONTROLLERCHANGED (WM_USER + 123)
+#define WM_SYS_SHUTDOWNREQUEST (WM_USER + 124)
+
+#if defined( _PS3 )
+#define PLATFORM_EXT ".ps3"
+#elif defined( PLATFORM_X360 )
+#define PLATFORM_EXT ".360"
+#else
+#define PLATFORM_EXT ""
+#endif
+
+inline const char *GetPlatformExt( void )
+{
+ return PLATFORM_EXT;
+}
+
+// flat view, 6 hw threads
+#define XBOX_PROCESSOR_0 ( 1<<0 )
+#define XBOX_PROCESSOR_1 ( 1<<1 )
+#define XBOX_PROCESSOR_2 ( 1<<2 )
+#define XBOX_PROCESSOR_3 ( 1<<3 )
+#define XBOX_PROCESSOR_4 ( 1<<4 )
+#define XBOX_PROCESSOR_5 ( 1<<5 )
+
+// core view, 3 cores with 2 hw threads each
+#define XBOX_CORE_0_HWTHREAD_0 XBOX_PROCESSOR_0
+#define XBOX_CORE_0_HWTHREAD_1 XBOX_PROCESSOR_1
+#define XBOX_CORE_1_HWTHREAD_0 XBOX_PROCESSOR_2
+#define XBOX_CORE_1_HWTHREAD_1 XBOX_PROCESSOR_3
+#define XBOX_CORE_2_HWTHREAD_0 XBOX_PROCESSOR_4
+#define XBOX_CORE_2_HWTHREAD_1 XBOX_PROCESSOR_5
+
+//-----------------------------------------------------------------------------
+// Include additional dependant header components.
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_X360 )
+#include "xbox/xbox_core.h"
+#elif defined( PLATFORM_PS3 )
+#include "ps3/ps3_core.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Methods to invoke the constructor, copy constructor, and destructor
+//-----------------------------------------------------------------------------
+
+template <class T>
+inline T* Construct( T* pMemory )
+{
+ return ::new( pMemory ) T;
+}
+
+template <class T, typename ARG1>
+inline T* Construct( T* pMemory, ARG1 a1 )
+{
+ return ::new( pMemory ) T( a1 );
+}
+
+template <class T, typename ARG1, typename ARG2>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
+{
+ return ::new( pMemory ) T( a1, a2 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3 )
+{
+ return ::new( pMemory ) T( a1, a2, a3 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4 )
+{
+ return ::new( pMemory ) T( a1, a2, a3, a4 );
+}
+
+template <class T, typename ARG1, typename ARG2, typename ARG3, typename ARG4, typename ARG5>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2, ARG3 a3, ARG4 a4, ARG5 a5 )
+{
+ return ::new( pMemory ) T( a1, a2, a3, a4, a5 );
+}
+
+template <class T>
+inline T* CopyConstruct( T* pMemory, T const& src )
+{
+ return ::new( pMemory ) T(src);
+}
+
+template <class T>
+inline void Destruct( T* pMemory )
+{
+ pMemory->~T();
+
+#ifdef _DEBUG
+ memset( pMemory, 0xDD, sizeof(T) );
+#endif
+}
+
+
+//
+// GET_OUTER()
+//
+// A platform-independent way for a contained class to get a pointer to its
+// owner. If you know a class is exclusively used in the context of some
+// "outer" class, this is a much more space efficient way to get at the outer
+// class than having the inner class store a pointer to it.
+//
+// class COuter
+// {
+// class CInner // Note: this does not need to be a nested class to work
+// {
+// void PrintAddressOfOuter()
+// {
+// printf( "Outer is at 0x%x\n", GET_OUTER( COuter, m_Inner ) );
+// }
+// };
+//
+// CInner m_Inner;
+// friend class CInner;
+// };
+
+#define GET_OUTER( OuterType, OuterMember ) \
+ ( ( OuterType * ) ( (uint8 *)this - offsetof( OuterType, OuterMember ) ) )
+
+
+/* TEMPLATE_FUNCTION_TABLE()
+
+ (Note added to platform.h so platforms that correctly support templated
+ functions can handle portions as templated functions rather than wrapped
+ functions)
+
+ Helps automate the process of creating an array of function
+ templates that are all specialized by a single integer.
+ This sort of thing is often useful in optimization work.
+
+ For example, using TEMPLATE_FUNCTION_TABLE, this:
+
+ TEMPLATE_FUNCTION_TABLE(int, Function, ( int blah, int blah ), 10)
+ {
+ return argument * argument;
+ }
+
+ is equivilent to the following:
+
+ (NOTE: the function has to be wrapped in a class due to code
+ generation bugs involved with directly specializing a function
+ based on a constant.)
+
+ template<int argument>
+ class FunctionWrapper
+ {
+ public:
+ int Function( int blah, int blah )
+ {
+ return argument*argument;
+ }
+ }
+
+ typedef int (*FunctionType)( int blah, int blah );
+
+ class FunctionName
+ {
+ public:
+ enum { count = 10 };
+ FunctionType functions[10];
+ };
+
+ FunctionType FunctionName::functions[] =
+ {
+ FunctionWrapper<0>::Function,
+ FunctionWrapper<1>::Function,
+ FunctionWrapper<2>::Function,
+ FunctionWrapper<3>::Function,
+ FunctionWrapper<4>::Function,
+ FunctionWrapper<5>::Function,
+ FunctionWrapper<6>::Function,
+ FunctionWrapper<7>::Function,
+ FunctionWrapper<8>::Function,
+ FunctionWrapper<9>::Function
+ };
+*/
+
+PLATFORM_INTERFACE bool vtune( bool resume );
+
+
+#define TEMPLATE_FUNCTION_TABLE(RETURN_TYPE, NAME, ARGS, COUNT) \
+ \
+typedef RETURN_TYPE (FASTCALL *__Type_##NAME) ARGS; \
+ \
+template<const int nArgument> \
+struct __Function_##NAME \
+{ \
+ static RETURN_TYPE FASTCALL Run ARGS; \
+}; \
+ \
+template <const int i> \
+struct __MetaLooper_##NAME : __MetaLooper_##NAME<i-1> \
+{ \
+ __Type_##NAME func; \
+ inline __MetaLooper_##NAME() { func = __Function_##NAME<i>::Run; } \
+}; \
+ \
+template<> \
+struct __MetaLooper_##NAME<0> \
+{ \
+ __Type_##NAME func; \
+ inline __MetaLooper_##NAME() { func = __Function_##NAME<0>::Run; } \
+}; \
+ \
+class NAME \
+{ \
+private: \
+ static const __MetaLooper_##NAME<COUNT> m; \
+public: \
+ enum { count = COUNT }; \
+ static const __Type_##NAME* functions; \
+}; \
+const __MetaLooper_##NAME<COUNT> NAME::m; \
+const __Type_##NAME* NAME::functions = (__Type_##NAME*)&m; \
+template<const int nArgument> \
+RETURN_TYPE FASTCALL __Function_##NAME<nArgument>::Run ARGS
+
+
+#define LOOP_INTERCHANGE(BOOLEAN, CODE)\
+ if( (BOOLEAN) )\
+ {\
+ CODE;\
+ } else\
+ {\
+ CODE;\
+ }
+
+
+//-----------------------------------------------------------------------------
+// Dynamic libs support
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_WINDOWS )
+
+PLATFORM_INTERFACE void *Plat_GetProcAddress( const char *pszModule, const char *pszName );
+
+template <typename FUNCPTR_TYPE>
+class CDynamicFunction
+{
+public:
+ CDynamicFunction( const char *pszModule, const char *pszName, FUNCPTR_TYPE pfnFallback = NULL )
+ {
+ m_pfn = pfnFallback;
+ void *pAddr = Plat_GetProcAddress( pszModule, pszName );
+ if ( pAddr )
+ {
+ m_pfn = (FUNCPTR_TYPE)pAddr;
+ }
+ }
+
+ operator bool() { return m_pfn != NULL; }
+ bool operator !() { return !m_pfn; }
+ operator FUNCPTR_TYPE() { return m_pfn; }
+
+private:
+ FUNCPTR_TYPE m_pfn;
+};
+#endif
+
+
+//-----------------------------------------------------------------------------
+// What OS version are we?
+//-----------------------------------------------------------------------------
+enum PlatOSVersion_t
+{
+ PLAT_OS_VERSION_UNKNOWN = -1,
+
+ // X360-specific versions
+ PLAT_OS_VERSION_XBOX360 = 0,
+
+ // PC-specific OS versions
+ PLAT_OS_VERSION_XP = 5,
+ PLAT_OS_VERSION_VISTA = 6,
+};
+
+PLATFORM_INTERFACE PlatOSVersion_t Plat_GetOSVersion();
+
+
+// Watchdog timer support. Call BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
+// EndWatchdogTimer within nn seconds, the program will kick off an exception. This is for making
+// sure that hung dedicated servers abort (and restart) instead of staying hung. Calling
+// EndWatchdogTimer more than once or when there is no active watchdog is fine. Only does anything
+// under linux right now. It should be possible to implement this functionality in windows via a
+// thread, if desired.
+
+#if defined( POSIX ) && !defined( _PS3 )
+
+PLATFORM_INTERFACE void BeginWatchdogTimer( int nSecs );
+PLATFORM_INTERFACE void EndWatchdogTimer( void );
+PLATFORM_INTERFACE void ResetBaseTime( void ); // reset plat_floattime to 0 for a subprocess
+#else
+FORCEINLINE void BeginWatchdogTimer( int nSecs )
+{
+}
+
+FORCEINLINE void EndWatchdogTimer( void )
+{
+}
+FORCEINLINE void ResetBaseTime( void ) // reset plat_floattime to 0 for a subprocess
+{
+}
+
+#endif
+
+
+#ifdef COMPILER_MSVC
+/*
+FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
+{
+ return _rotl8( nValue, nRotateBits );
+}
+FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
+{
+ return _rotl( nValue, nRotateBits );
+}
+FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
+{
+return _rotr8( nValue, nRotateBits );
+}
+FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
+{
+return _rotr16( nValue, nRotateBits );
+}
+*/
+FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
+{
+ return _rotl( nValue, nRotateBits );
+}
+FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
+{
+ return _rotl64( nValue, nRotateBits );
+}
+FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
+{
+ return _rotr( nValue, nRotateBits );
+}
+FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
+{
+ return _rotr64( nValue, nRotateBits );
+}
+#else
+// GCC should compile this all into single instruction
+/*
+FORCEINLINE uint8 RotateBitsLeft8( uint8 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 7 ) );
+}
+FORCEINLINE uint16 RotateBitsLeft16( uint16 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 15 ) );
+}
+FORCEINLINE uint8 RotateBitsRight8( uint8 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 7 ) );
+}
+FORCEINLINE uint16 RotateBitsRight16( uint16 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 15 ) );
+}
+*/
+FORCEINLINE uint32 RotateBitsLeft32( uint32 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( -nRotateBits ) & 31 ) );
+}
+FORCEINLINE uint64 RotateBitsLeft64( uint64 nValue, int nRotateBits )
+{
+ return ( nValue << nRotateBits ) | ( nValue >> ( ( - nRotateBits ) & 63 ) );
+}
+FORCEINLINE uint32 RotateBitsRight32( uint32 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( -nRotateBits ) & 31 ) );
+}
+FORCEINLINE uint64 RotateBitsRight64( uint64 nValue, int nRotateBits )
+{
+ return ( nValue >> nRotateBits ) | ( nValue << ( ( - nRotateBits ) & 63 ) );
+}
+#endif
+PLATFORM_INTERFACE const char * GetPlatformSpecificFileName(const char * FileName);
+
+#include "tier0/valve_on.h"
+
+#if defined(TIER0_DLL_EXPORT)
+extern "C" int V_tier0_stricmp(const char *s1, const char *s2 );
+#undef stricmp
+#undef strcmpi
+#define stricmp(s1,s2) V_tier0_stricmp( s1, s2 )
+#define strcmpi(s1,s2) V_tier0_stricmp( s1, s2 )
+#else
+int _V_stricmp (const char *s1, const char *s2 );
+int V_strncasecmp (const char *s1, const char *s2, int n);
+
+// A special high-performance case-insensitive compare function that in
+// a single call distinguishes between exactly matching strings,
+// strings equal in case-insensitive way, and not equal strings:
+// returns 0 if strings match exactly
+// returns >0 if strings match in a case-insensitive way, but do not match exactly
+// returns <0 if strings do not match even in a case-insensitive way
+int _V_stricmp_NegativeForUnequal ( const char *s1, const char *s2 );
+
+#undef stricmp
+#undef strcmpi
+#define stricmp(s1,s2) _V_stricmp(s1, s2)
+#define strcmpi(s1,s2) _V_stricmp(s1, s2)
+#undef strnicmp
+#define strnicmp V_strncasecmp
+#endif
+
+#endif /* PLATFORM_H */
diff --git a/external/vpc/public/tier0/pmelib.h b/external/vpc/public/tier0/pmelib.h
new file mode 100644
index 0000000..dcdec5f
--- /dev/null
+++ b/external/vpc/public/tier0/pmelib.h
@@ -0,0 +1,212 @@
+//===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+#ifndef PMELIB_H
+#define PMELIB_H
+
+//#include "windows.h"
+
+#include "tier0/platform.h"
+
+// Get rid of a bunch of STL warnings!
+#pragma warning( push, 3 )
+#pragma warning( disable : 4018 )
+
+#define VERSION "1.0.2"
+
+// uncomment this list to add some runtime checks
+//#define PME_DEBUG
+
+#include "tier0/valve_off.h"
+#include <string>
+#include "tier0/valve_on.h"
+
+using namespace std;
+
+// RDTSC Instruction macro
+#ifdef COMPILER_MSVC64
+#define RDTSC(var) (var = __rdtsc())
+#else
+#define RDTSC(var) \
+_asm RDTSC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+// RDPMC Instruction macro
+#ifdef COMPILER_MSVC64
+#define RDPMC(counter, var) (var = __readpmc(counter))
+#else
+#define RDPMC(counter, var) \
+_asm mov ecx, counter \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+// RDPMC Instruction macro, for performance counter 1 (ecx = 1)
+#ifdef COMPILER_MSVC64
+#define RDPMC0(var) (var = __readpmc(0))
+#else
+#define RDPMC0(var) \
+_asm mov ecx, 0 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+#ifdef COMPILER_MSVC64
+#define RDPMC1(var) (var = __readpmc(1))
+#else
+#define RDPMC1(var) \
+_asm mov ecx, 1 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+#endif
+
+#define EVENT_TYPE(mode) EventType##mode
+#define EVENT_MASK(mode) EventMask##mode
+
+#include "ia32detect.h"
+
+enum ProcessPriority
+{
+ ProcessPriorityNormal,
+ ProcessPriorityHigh,
+};
+
+enum PrivilegeCapture
+{
+ OS_Only, // ring 0, kernel level
+ USR_Only, // app level
+ OS_and_USR, // all levels
+};
+
+enum CompareMethod
+{
+ CompareGreater, //
+ CompareLessEqual, //
+};
+
+enum EdgeState
+{
+ RisingEdgeDisabled, //
+ RisingEdgeEnabled, //
+};
+
+enum CompareState
+{
+ CompareDisable, //
+ CompareEnable, //
+};
+
+// Singletion Class
+class PME : public ia32detect
+{
+public:
+//private:
+
+ static PME* _singleton;
+
+ HANDLE hFile;
+ bool bDriverOpen;
+ double m_CPUClockSpeed;
+
+ //ia32detect detect;
+ HRESULT Init();
+ HRESULT Close();
+
+protected:
+
+ PME()
+ {
+ hFile = NULL;
+ bDriverOpen = FALSE;
+ m_CPUClockSpeed = 0;
+ Init();
+ }
+
+public:
+
+ static PME* Instance(); // gives back a real object
+
+ ~PME()
+ {
+ Close();
+ }
+
+ double GetCPUClockSpeedSlow( void );
+ double GetCPUClockSpeedFast( void );
+
+ HRESULT SelectP5P6PerformanceEvent( uint32 dw_event, uint32 dw_counter, bool b_user, bool b_kernel );
+
+ HRESULT ReadMSR( uint32 dw_reg, int64 * pi64_value );
+ HRESULT ReadMSR( uint32 dw_reg, uint64 * pi64_value );
+
+ HRESULT WriteMSR( uint32 dw_reg, const int64 & i64_value );
+ HRESULT WriteMSR( uint32 dw_reg, const uint64 & i64_value );
+
+ void SetProcessPriority( ProcessPriority priority )
+ {
+ switch( priority )
+ {
+ case ProcessPriorityNormal:
+ {
+ SetPriorityClass (GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
+ SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_NORMAL);
+ break;
+ }
+ case ProcessPriorityHigh:
+ {
+ SetPriorityClass (GetCurrentProcess(),REALTIME_PRIORITY_CLASS);
+ SetThreadPriority (GetCurrentThread(),THREAD_PRIORITY_HIGHEST);
+ break;
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ // Return the family of the processor
+ //---------------------------------------------------------------------------
+ CPUVendor GetVendor(void)
+ {
+ return vendor;
+ }
+
+ int GetProcessorFamily(void)
+ {
+ return version.Family;
+ }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+};
+
+#include "p5p6performancecounters.h"
+#include "p4performancecounters.h"
+#include "k8performancecounters.h"
+
+enum PerfErrors
+{
+ E_UNKNOWN_CPU_VENDOR = -1,
+ E_BAD_COUNTER = -2,
+ E_UNKNOWN_CPU = -3,
+ E_CANT_OPEN_DRIVER = -4,
+ E_DRIVER_ALREADY_OPEN = -5,
+ E_DRIVER_NOT_OPEN = -6,
+ E_DISABLED = -7,
+ E_BAD_DATA = -8,
+ E_CANT_CLOSE = -9,
+ E_ILLEGAL_OPERATION = -10,
+};
+
+#pragma warning( pop )
+
+#endif // PMELIB_H \ No newline at end of file
diff --git a/external/vpc/public/tier0/stackstats.h b/external/vpc/public/tier0/stackstats.h
new file mode 100644
index 0000000..a14d64b
--- /dev/null
+++ b/external/vpc/public/tier0/stackstats.h
@@ -0,0 +1,966 @@
+//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Tools for grabbing/dumping the stack at runtime
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TIER0_STACKSTATS_H
+#define TIER0_STACKSTATS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/stacktools.h"
+#include "tier0/threadtools.h"
+
+#if defined ENABLE_RUNTIME_STACK_TRANSLATION
+#define ENABLE_STACK_STATS_GATHERING //uncomment to enable the gathering class
+#endif
+
+#if defined ENABLE_STACK_STATS_GATHERING
+#include "tier0/valve_off.h"
+# include <map> //needed for CCallStackStatsGatherer
+# include <vector>
+#include "tier0/valve_on.h"
+#define CDefaultStatsGathererAllocator std::allocator
+#else
+template<class _Ty> class CNullStatsGathererAllocator { CNullStatsGathererAllocator( void ) { } };
+#define CDefaultStatsGathererAllocator CNullStatsGathererAllocator
+#endif
+
+
+typedef size_t (*FN_DescribeStruct)( uint8 *, size_t );
+
+class CCallStackStatsGatherer_Standardized_t;
+struct CCallStackStatsGatherer_FunctionTable_t
+{
+ void (*pfn_GetDumpInfo)( void *, const char *&, size_t &, size_t &, void *&, size_t &, CCallStackStatsGatherer_Standardized_t *&, size_t & );
+ void (*pfn_PushSubTree)( void *, const CCallStackStatsGatherer_Standardized_t &, const CCallStackStorage & );
+ void (*pfn_PopSubTree)( void * );
+ size_t (*pfn_DescribeCallStackStatStruct)( uint8 *, size_t );
+ void (*pfn_SyncMutexes)( void *, bool );
+ void *(*pfn_GetEntry)( void *, uint32 );
+ void (*pfn_ApplyTreeAccessLock)( void *, bool );
+ void (*pfn_LockEntry)( void *, uint32, bool );
+};
+
+//templatized classes are fun, can't really use a base pointer effectively, so we'll have a translator struct and store pointers to instances of the translator function
+class CCallStackStatsGatherer_Standardized_t
+{
+public:
+ CCallStackStatsGatherer_Standardized_t( void ) {};
+ CCallStackStatsGatherer_Standardized_t( void *pThis, const CCallStackStatsGatherer_FunctionTable_t &FnTable ) : pGatherer( pThis ), pFunctionTable( &FnTable ) {};
+
+ //go ahead and create some helper functions that are likely to be used by helper code
+ void PushSubTree( const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack = CCallStackStorage() ) const
+ {
+ pFunctionTable->pfn_PushSubTree( pGatherer, SubTree, PushStack );
+ }
+
+ inline void PopSubTree( void ) const
+ {
+ pFunctionTable->pfn_PopSubTree( pGatherer );
+ }
+
+ void *pGatherer;
+ const CCallStackStatsGatherer_FunctionTable_t *pFunctionTable;
+};
+
+//Designed to be called by an instance of CCallStackStatsGatherer to dump it's data
+PLATFORM_INTERFACE bool _CCallStackStatsGatherer_Internal_DumpStatsToFile( const char *szFileName, const CCallStackStatsGatherer_Standardized_t &StatsGatherer, bool bAllowMemoryAllocations );
+
+
+
+
+
+
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_Base
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_Base( const CCallStackStatsGatherer_Standardized_t &Gatherer, int iEntryIndex ) : m_Gatherer( Gatherer ), m_iEntryIndex( iEntryIndex ) {};
+protected:
+ uint32 m_iEntryIndex; //index of the stat entry we want in the vector. Stored as index as the vector base address can change.
+ CCallStackStatsGatherer_Standardized_t m_Gatherer; //so we can lock the vector memory in place while manipulating the values
+};
+
+
+class CCallStackStatsGatherer_StatMutexBase
+{
+public:
+ void LockEntry( uint32 iEntryIndex, bool bLock ) {} //true to increase lock refcount, false to decrease
+};
+
+template <uint32 SHAREDENTRYMUTEXES> //must be a power of 2
+class CCallStackStatsGatherer_StatMutexPool
+{
+public:
+ void LockEntry( uint32 iEntryIndex, bool bLock )
+ {
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( (SHAREDENTRYMUTEXES & (SHAREDENTRYMUTEXES - 1)) == 0 ); //must be a power of 2
+
+ if( bLock )
+ {
+ m_IndividualEntryMutexes[iEntryIndex & (SHAREDENTRYMUTEXES - 1)].Lock();
+ }
+ else
+ {
+ m_IndividualEntryMutexes[iEntryIndex & (SHAREDENTRYMUTEXES - 1)].Unlock();
+ }
+#endif
+ }
+protected:
+ CThreadFastMutex m_IndividualEntryMutexes[SHAREDENTRYMUTEXES];
+};
+
+
+
+
+//STATSTRUCT - The structure you'll use to track whatever it is you're tracking.
+//CAPTUREDCALLSTACKLENGTH - The maximum length of your stack trace that we'll use to distinguish entries
+//STACKACQUISITIONFUNCTION - The function to use to gather the current call stack. GetCallStack() is safe, GetCallStack_Fast() is faster, but has special requirements
+//STATMUTEXHANDLER - If you want automatic mutex management for your individual entries, supply a handler here.
+// You'll need to not only call GetEntry(), but lock/unlock the entry while accessing it.
+//TEMPLATIZEDMEMORYALLOCATOR - We'll need to allocate memory, supply an allocator if you want to manage that
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION = GetCallStack, typename STATMUTEXHANDLER = CCallStackStatsGatherer_StatMutexPool<4>, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR = CDefaultStatsGathererAllocator>
+class CCallStackStatsGatherer : public STATMUTEXHANDLER
+{
+public:
+#if !defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer( void )
+ {
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ m_SingleCallStack[i] = NULL;
+ }
+#endif
+
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH] ); //get the entry using some callstack grabbed a while ago. Assumes ALL invalid entries have been nullified
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ); //same as above, but does the work of nullifying invalid entries
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+ CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> GetEntry( uint32 iEntryIndex );
+
+ //get the entry index for the caller's current call stack. Pre-nullified entries count as valid entries (and save re-nullification work)
+ uint32 GetEntryIndex( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ); //index is unchanging, safe to keep and use later (designed for exactly that purpose)
+ uint32 GetEntryIndex( const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+
+
+
+ typedef void *(&StackReference)[CAPTUREDCALLSTACKLENGTH];
+ StackReference GetCallStackForIndex( uint32 iEntryIndex )
+ {
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return m_StatEntries[iEntryIndex].m_CallStack;
+#else
+ return m_SingleCallStack;
+#endif
+ }
+
+ void GetCallStackForIndex( uint32 iEntryIndex, void *CallStackOut[CAPTUREDCALLSTACKLENGTH] );
+
+ size_t NumEntries( void ) const;
+
+ bool DumpToFile( const char *szFileName, bool bAllowMemoryAllocations = true );
+
+ static const CCallStackStatsGatherer_FunctionTable_t &GetFunctionTable( void );
+
+ static void GetDumpInfo( void *pThis, const char *&szStructName, size_t &iCapturedStackLength, size_t &iEntrySizeWithStack, void *&pEntries, size_t &iEntryCount, CCallStackStatsGatherer_Standardized_t *&pSubTrees, size_t &iSubTreeCount );
+ static void PushSubTree( void *pParent, const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack );
+
+ void PushSubTree( CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStorage &PushStack = CCallStackStorage( STACKACQUISITIONFUNCTION ) );
+
+ static void PopSubTree( void *pParent );
+ static void SyncMutexes( void *pParent, bool bLock ); //true for lock, false for unlock
+ static void *GetEntry( void *pParent, uint32 iEntryIndex );
+ static void ApplyTreeAccessLock( void *pParent, bool bLock );
+ static void LockEntry( void *pParent, uint32 iEntryIndex, bool bLock );
+
+ void Reset( void );
+
+
+ CCallStackStatsGatherer_Standardized_t Standardized( void );
+ operator CCallStackStatsGatherer_Standardized_t( void );
+
+ const static FN_GetCallStack StackFunction; //publish the requested acquisition function so you can easily key all your stack gathering to the class instance
+ const static size_t CapturedCallStackLength;
+private:
+
+#pragma pack(push)
+#pragma pack(1)
+ struct StackAndStats_t
+ {
+ void *m_CallStack[CAPTUREDCALLSTACKLENGTH];
+ STATSTRUCT m_Stats;
+ };
+#pragma pack(pop)
+
+ typedef CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR> ThisCast;
+
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+
+ struct IndexMapKey_t
+ {
+ IndexMapKey_t( void * const CallStack[CAPTUREDCALLSTACKLENGTH] )
+ {
+ m_Hash = 0;
+ for( int i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ m_CallStack[i] = CallStack[i];
+ m_Hash += (uintp)CallStack[i];
+ }
+ }
+ bool operator<( const IndexMapKey_t &key ) const
+ {
+ if( m_Hash != key.m_Hash )
+ return m_Hash < key.m_Hash;
+
+ //only here if there's a hash match. Do a full check. Extremely likely to be the exact same call stack. But not 100% guaranteed.
+ for( int i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ if( m_CallStack[i] == key.m_CallStack[i] )
+ {
+ continue;
+ }
+
+ return m_CallStack[i] < key.m_CallStack[i];
+ }
+
+ return false; //exact same call stack
+ }
+
+ uintp m_Hash;
+ void *m_CallStack[CAPTUREDCALLSTACKLENGTH];
+ };
+
+ void KeepSubTree( CCallStackStatsGatherer_Standardized_t &SubTree )
+ {
+ AUTO_LOCK_FM( m_SubTreeMutex );
+ for( StoredSubTreeVector_t::iterator treeIter = m_StoredSubTrees.begin(); treeIter != m_StoredSubTrees.end(); ++treeIter )
+ {
+ if( SubTree.pGatherer == treeIter->pGatherer )
+ return;
+ }
+
+ //Warning( "Storing subtree\n" );
+
+ m_StoredSubTrees.push_back( SubTree );
+ }
+
+ uint32 PatchInSubTrees( void * const CallStackIn[CAPTUREDCALLSTACKLENGTH], void *CallStackOut[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries )
+ {
+ if( iValidEntries > CAPTUREDCALLSTACKLENGTH )
+ {
+ iValidEntries = CAPTUREDCALLSTACKLENGTH;
+ }
+
+ AUTO_LOCK_FM( m_SubTreeMutex );
+ if( m_PushedSubTrees.size() == 0 )
+ {
+ memcpy( CallStackOut, CallStackIn, sizeof( void * ) * iValidEntries );
+ return iValidEntries;
+ }
+
+ unsigned long iThreadID = ThreadGetCurrentId();
+ PushedSubTreeVector_t::reverse_iterator treeIter;
+ for( treeIter = m_PushedSubTrees.rbegin(); treeIter != m_PushedSubTrees.rend(); ++treeIter )
+ {
+ if( treeIter->iThreadID == iThreadID )
+ {
+ break;
+ }
+ }
+
+ if( treeIter == m_PushedSubTrees.rend() )
+ {
+ memcpy( CallStackOut, CallStackIn, sizeof( void * ) * iValidEntries );
+ return iValidEntries;
+ }
+
+ //char szTemp[4096];
+ //TranslateStackInfo( CallStackIn, CAPTUREDCALLSTACKLENGTH, szTemp, sizeof( szTemp ), "\n\t" );
+
+ //Warning( "Attempting to link trees:\n=======================ONE=======================\n\t%s\n", szTemp );
+ //TranslateStackInfo( treeIter->Stack, CAPTUREDCALLSTACKLENGTH, szTemp, sizeof( szTemp ), "\n\t" );
+ //Warning( "=======================TWO=======================\n\t%s\n", szTemp );
+
+ void *pMatchAddress = treeIter->Stack[1]; //while the first entry is where the actual push was made. The second entry is the first that is matchable in most cases
+
+ uint32 i;
+ for( i = 0; i < iValidEntries; ++i )
+ {
+ if( CallStackIn[i] == pMatchAddress )
+ {
+ //TranslateStackInfo( CallStackIn, i, szTemp, sizeof( szTemp ), "\n\t" );
+ //Warning( "======================MATCH======================\n\t%s\n", szTemp );
+
+ CallStackOut[i] = treeIter->tree.pGatherer; //tag this entry as leading into the sub-tree
+ KeepSubTree( treeIter->tree ); //store the sub-tree forever
+ return i + 1;
+ }
+ CallStackOut[i] = CallStackIn[i];
+ }
+
+ return iValidEntries;
+
+ //Warning( "=======================END=======================\n" );
+ }
+
+ struct StatIndex_t
+ {
+ StatIndex_t( void ) : m_Index((unsigned int)-1) {};
+ unsigned int m_Index;
+ };
+
+ typedef std::vector<StackAndStats_t, TEMPLATIZEDMEMORYALLOCATOR<StackAndStats_t> > StatVector_t;
+ typedef std::map< IndexMapKey_t, StatIndex_t, std::less<IndexMapKey_t>, TEMPLATIZEDMEMORYALLOCATOR<std::pair<const IndexMapKey_t, StatIndex_t> > > IndexMap_t;
+ typedef typename IndexMap_t::iterator IndexMapIter_t;
+ typedef typename IndexMap_t::value_type IndexMapEntry_t;
+
+ StatVector_t m_StatEntries;
+ IndexMap_t m_IndexMap;
+
+ struct PushedSubTree_t
+ {
+ unsigned long iThreadID;
+ CCallStackStatsGatherer_Standardized_t tree;
+ void *Stack[CAPTUREDCALLSTACKLENGTH];
+ };
+
+ typedef std::vector<PushedSubTree_t, TEMPLATIZEDMEMORYALLOCATOR<PushedSubTree_t> > PushedSubTreeVector_t;
+ PushedSubTreeVector_t m_PushedSubTrees;
+
+ typedef std::vector<CCallStackStatsGatherer_Standardized_t, TEMPLATIZEDMEMORYALLOCATOR<CCallStackStatsGatherer_Standardized_t> > StoredSubTreeVector_t;
+ StoredSubTreeVector_t m_StoredSubTrees;
+
+ CThreadFastMutex m_IndexMapMutex;
+ CThreadFastMutex m_SubTreeMutex;
+
+ //only for locking the memory in place, locked for write when the entry addresses might change.
+ //Locked for read when you've claimed you're manipulating a value.
+ //You're on your own for making sure two threads don't access the same index simultaneously
+ CThreadRWLock m_StatEntryLock;
+
+#else //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+ STATSTRUCT m_SingleEntry; //the class is disabled, we'll always return this same struct
+ void *m_SingleCallStack[CAPTUREDCALLSTACKLENGTH];
+
+ static size_t NULL_DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) { return 0; }
+
+#endif //#if defined( ENABLE_STACK_STATS_GATHERING )
+};
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const FN_GetCallStack CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::StackFunction = STACKACQUISITIONFUNCTION;
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const size_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::CapturedCallStackLength = CAPTUREDCALLSTACKLENGTH;
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+
+class CallStackStatStructDescFuncs;
+PLATFORM_INTERFACE size_t _CCallStackStatsGatherer_Write_FieldDescriptions( CallStackStatStructDescFuncs *pFieldDescriptions, uint8 *pWriteBuffer, size_t iWriteBufferSize );
+//PLATFORM_INTERFACE size_t _CCallStackStatsGatherer_Write_FieldMergeScript( CallStackStatStructDescFuncs *pFieldDescriptions, CallStackStatStructDescFuncs::MergeScript_Language scriptMergeLanguage, uint8 *pWriteBuffer, size_t iWriteBufferSize );
+
+#define DECLARE_CALLSTACKSTATSTRUCT() static const char *STATSTRUCTSTRINGNAME;\
+ static size_t DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+
+#define BEGIN_STATSTRUCTDESCRIPTION( className ) const char *className::STATSTRUCTSTRINGNAME = #className;\
+ size_t className::DescribeCallStackStatStruct( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) {\
+ size_t iWroteBytes = 0;
+#define END_STATSTRUCTDESCRIPTION() return iWroteBytes; }
+
+
+#define DECLARE_CALLSTACKSTATSTRUCT_FIELDDESCRIPTION() static CallStackStatStructDescFuncs *GetStatStructFieldDescriptions( void );
+
+#define BEGIN_STATSTRUCTFIELDDESCRIPTION( className ) CallStackStatStructDescFuncs * className::GetStatStructFieldDescriptions( void ) {\
+ typedef className ThisStruct;\
+ CallStackStatStructDescFuncs *_pHeadLinkage = NULL;\
+ CallStackStatStructDescFuncs **_pLinkageHelperVar = &_pHeadLinkage;
+
+#define _DEFINE_STATSTRUCTFIELD_VARNAME( varName, fieldName, fieldStruct, fieldParmsInParentheses ) static fieldStruct varName##_desc##fieldParmsInParentheses;\
+ varName##_desc.m_szFieldName = #fieldName;\
+ varName##_desc.m_iFieldOffset = (size_t)(&((ThisStruct *)NULL)->fieldName);\
+ varName##_desc.m_pNext = NULL;\
+ *_pLinkageHelperVar = &varName##_desc;\
+ _pLinkageHelperVar = &varName##_desc.m_pNext;
+
+#define DEFINE_STATSTRUCTFIELD( fieldName, fieldStruct, fieldParmsInParentheses ) _DEFINE_STATSTRUCTFIELD_VARNAME( fieldName, fieldName, fieldStruct, fieldParmsInParentheses )
+#define DEFINE_STATSTRUCTFIELD_ARRAYENTRY( arrayName, arrayIndex, fieldStruct, fieldParmsInParentheses ) _DEFINE_STATSTRUCTFIELD_VARNAME( arrayName##_##arrayIndex, arrayName##[##arrayIndex##], fieldStruct, fieldParmsInParentheses )
+
+#define END_STATSTRUCTFIELDDESCRIPTION() static CallStackStatStructDescFuncs *s_pHeadStruct = _pHeadLinkage;\
+ return s_pHeadStruct; }
+
+#define WRITE_STATSTRUCT_FIELDDESCRIPTION() iWroteBytes += _CCallStackStatsGatherer_Write_FieldDescriptions( GetStatStructFieldDescriptions(), pDescribeWriteBuffer + iWroteBytes, iDescribeMaxLength - iWroteBytes );
+//#define WRITE_STATSTRUCT_FIELDMERGESCRIPT( scriptMergeLanguage ) iWroteBytes += _CCallStackStatsGatherer_Write_FieldMergeScript( GetStatStructFieldDescriptions(), CallStackStatStructDescFuncs::scriptMergeLanguage, pDescribeWriteBuffer + iWroteBytes, iDescribeMaxLength - iWroteBytes );
+
+
+#else //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+#define DECLARE_CALLSTACKSTATSTRUCT()
+#define BEGIN_STATSTRUCTDESCRIPTION( className )
+#define END_STATSTRUCTDESCRIPTION()
+
+#define DECLARE_CALLSTACKSTATSTRUCT_FIELDDESCRIPTION()
+#define BEGIN_STATSTRUCTFIELDDESCRIPTION( className )
+#define DEFINE_STATSTRUCTFIELD( fieldName, fieldStruct, fieldParmsInParentheses )
+#define END_STATSTRUCTFIELDDESCRIPTION()
+
+#define WRITE_STATSTRUCT_FIELDDESCRIPTION()
+//#define WRITE_STATSTRUCT_FIELDMERGESCRIPT( scriptMergeLanguage )
+
+#endif //#if defined( ENABLE_STACK_STATS_GATHERING )
+
+
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH] ) //get the entry using some callstack grabbed a while ago. Assumes ALL invalid entries have been nullified
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return GetEntry( GetEntryIndex( CallStack ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ) //same as above, but does the work of nullifying invalid entries
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ void *CleanedCallStack[CAPTUREDCALLSTACKLENGTH];
+ size_t i;
+ for( i = 0; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CleanedCallStack[i] = CallStack[i];
+ }
+
+ for( ; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CleanedCallStack[i] = NULL;
+ }
+ return GetEntry( GetEntryIndex( CleanedCallStack ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( CAPTUREDCALLSTACKLENGTH <= ARRAYSIZE( PushStack.pStack ) );
+ return GetEntry( GetEntryIndex( PushStack.pStack, PushStack.iValidEntries ) );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+uint32 CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntryIndex( const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ COMPILE_TIME_ASSERT( CAPTUREDCALLSTACKLENGTH <= ARRAYSIZE( PushStack.pStack ) );
+ return GetEntryIndex( PushStack.pStack, PushStack.iValidEntries );
+#else
+ return 0;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( uint32 iEntryIndex )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), iEntryIndex );
+#else
+ return CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( Standardized(), 0 );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+uint32 CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntryIndex( void * const CallStack[CAPTUREDCALLSTACKLENGTH], uint32 iValidEntries ) //index is unchanging, safe to keep and use later (designed for exactly that purpose)
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ AUTO_LOCK_FM( m_IndexMapMutex );
+ std::pair<IndexMapIter_t, bool> indexMapIter;
+ void *PatchedStack[CAPTUREDCALLSTACKLENGTH];
+
+ //if we have a sub-tree. We'll be splicing it into the original call stack as if it were a return address. Then patching that when we interpret the results later
+ //A stack with a sub-tree along the line is treated as distinctly different than one without a sub-tree
+ iValidEntries = PatchInSubTrees( CallStack, PatchedStack, iValidEntries );
+
+ Assert( iValidEntries <= CAPTUREDCALLSTACKLENGTH );
+
+ for( int i = iValidEntries; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ PatchedStack[i] = NULL;
+ }
+
+ indexMapIter = m_IndexMap.insert( IndexMapEntry_t( IndexMapKey_t( PatchedStack ), StatIndex_t() ) );
+
+ if( indexMapIter.first->second.m_Index == -1 )
+ {
+ m_StatEntryLock.LockForWrite();
+ indexMapIter.first->second.m_Index = (unsigned int)m_StatEntries.size();
+
+ m_StatEntries.push_back( StackAndStats_t() );
+ memcpy( m_StatEntries[indexMapIter.first->second.m_Index].m_CallStack, PatchedStack, sizeof( void * ) * CAPTUREDCALLSTACKLENGTH );
+ m_StatEntryLock.UnlockWrite();
+ }
+
+ return indexMapIter.first->second.m_Index;
+#else
+ return 0;
+#endif
+}
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetCallStackForIndex( uint32 iEntryIndex, void *CallStackOut[CAPTUREDCALLSTACKLENGTH] )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ m_StatEntryLock.LockForRead();
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ CallStackOut[i] = m_StatEntries[iEntryIndex].m_CallStack[i];
+ }
+ m_StatEntryLock.UnlockRead();
+#else
+ for( size_t i = 0; i != CAPTUREDCALLSTACKLENGTH; ++i )
+ CallStackOut[i] = NULL;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+size_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::NumEntries( void ) const
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return m_StatEntries.size();
+#else
+ return 0;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+bool CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::DumpToFile( const char *szFileName, bool bAllowMemoryAllocations )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer_Standardized_t StandardThis = Standardized();
+ SyncMutexes( this, true );
+ bool bRetVal = _CCallStackStatsGatherer_Internal_DumpStatsToFile( szFileName, StandardThis, bAllowMemoryAllocations );
+ SyncMutexes( this, false );
+ return bRetVal;
+#else
+ return false;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+const CCallStackStatsGatherer_FunctionTable_t &CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetFunctionTable( void )
+{
+ static CCallStackStatsGatherer_FunctionTable_t retVal =
+ { GetDumpInfo,
+ PushSubTree,
+ PopSubTree,
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ STATSTRUCT::DescribeCallStackStatStruct,
+#else
+ NULL_DescribeCallStackStatStruct,
+#endif
+ SyncMutexes,
+ GetEntry,
+ ApplyTreeAccessLock,
+ LockEntry };
+
+ return retVal;
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetDumpInfo( void *pThis, const char *&szStructName, size_t &iCapturedStackLength, size_t &iEntrySizeWithStack, void *&pEntries, size_t &iEntryCount, CCallStackStatsGatherer_Standardized_t *&pSubTrees, size_t &iSubTreeCount )
+{
+ ThisCast *pThisCast = (ThisCast *)pThis;
+ iCapturedStackLength = CAPTUREDCALLSTACKLENGTH;
+ iEntrySizeWithStack = sizeof( CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::StackAndStats_t );
+
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ szStructName = STATSTRUCT::STATSTRUCTSTRINGNAME;
+ iEntryCount = pThisCast->m_StatEntries.size();
+ pEntries = iEntryCount > 0 ? &pThisCast->m_StatEntries[0] : NULL;
+ iSubTreeCount = pThisCast->m_StoredSubTrees.size();
+ pSubTrees = iSubTreeCount > 0 ? &pThisCast->m_StoredSubTrees[0] : NULL;
+#else
+ szStructName = "";
+ iEntryCount = 0;
+ pEntries = NULL;
+ iSubTreeCount = 0;
+ pSubTrees = NULL;
+#endif
+}
+
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PushSubTree( void *pParent, const CCallStackStatsGatherer_Standardized_t &SubTree, const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ PushedSubTree_t pushVal;
+ pushVal.iThreadID = ThreadGetCurrentId();
+ pushVal.tree = SubTree;
+
+ memcpy( pushVal.Stack, PushStack.pStack, MIN( CAPTUREDCALLSTACKLENGTH, PushStack.iValidEntries ) * sizeof( void * ) );
+
+ for( int i = PushStack.iValidEntries; i < CAPTUREDCALLSTACKLENGTH; ++i )
+ {
+ pushVal.Stack[i] = NULL;
+ }
+
+ pParentCast->m_SubTreeMutex.Lock();
+ pParentCast->m_PushedSubTrees.push_back( pushVal );
+ pParentCast->m_SubTreeMutex.Unlock();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PushSubTree( CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStorage &PushStack )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ CCallStackStatsGatherer_Standardized_t StandardThis = Standardized();
+ Parent.PushSubTree( StandardThis, PushStack );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::PopSubTree( void *pParent )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ pParentCast->m_SubTreeMutex.Lock();
+ unsigned long iThreadID = ThreadGetCurrentId();
+
+ for( PushedSubTreeVector_t::reverse_iterator treeIter = pParentCast->m_PushedSubTrees.rbegin(); treeIter != pParentCast->m_PushedSubTrees.rend(); ++treeIter )
+ {
+ if( treeIter->iThreadID == iThreadID )
+ {
+ ++treeIter; //[24.4.1/1] &*(reverse_iterator(i)) == &*(i - 1)
+ PushedSubTreeVector_t::iterator eraseIter = treeIter.base();
+ pParentCast->m_PushedSubTrees.erase(eraseIter);
+ break;
+ }
+ }
+
+ pParentCast->m_SubTreeMutex.Unlock();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::SyncMutexes( void *pParent, bool bLock ) //true for lock, false for unlock
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ if( bLock )
+ {
+ pParentCast->m_IndexMapMutex.Lock();
+ pParentCast->m_SubTreeMutex.Lock();
+
+ for( StoredSubTreeVector_t::iterator treeIter = pParentCast->m_StoredSubTrees.begin(); treeIter != pParentCast->m_StoredSubTrees.end(); ++treeIter )
+ {
+ treeIter->pFunctionTable->pfn_SyncMutexes( treeIter->pGatherer, true );
+ }
+ }
+ else
+ {
+ for( StoredSubTreeVector_t::iterator treeIter = pParentCast->m_StoredSubTrees.begin(); treeIter != pParentCast->m_StoredSubTrees.end(); ++treeIter )
+ {
+ treeIter->pFunctionTable->pfn_SyncMutexes( treeIter->pGatherer, false );
+ }
+
+ pParentCast->m_IndexMapMutex.Unlock();
+ pParentCast->m_SubTreeMutex.Unlock();
+ }
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void *CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::GetEntry( void *pParent, uint32 iEntryIndex )
+{
+ ThisCast *pParentCast = (ThisCast *)pParent;
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ return &pParentCast->m_StatEntries[iEntryIndex].m_Stats;
+#else
+ return &pParentCast->m_SingleEntry;
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::ApplyTreeAccessLock( void *pParent, bool bLock )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ if( bLock )
+ {
+ pParentCast->m_StatEntryLock.LockForRead();
+ }
+ else
+ {
+ pParentCast->m_StatEntryLock.UnlockRead();
+ }
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::LockEntry( void *pParent, uint32 iEntryIndex, bool bLock )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ ThisCast *pParentCast = (ThisCast *)pParent;
+ pParentCast->STATMUTEXHANDLER::LockEntry( iEntryIndex, bLock );
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+void CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::Reset( void )
+{
+#if defined( ENABLE_STACK_STATS_GATHERING )
+ m_StatEntryLock.LockForWrite();
+ m_IndexMapMutex.Lock();
+ m_SubTreeMutex.Lock();
+
+ m_StatEntries.clear();
+ m_IndexMap.clear();
+ m_StoredSubTrees.clear();
+
+ m_SubTreeMutex.Unlock();
+ m_IndexMapMutex.Unlock();
+ m_StatEntryLock.UnlockWrite();
+#endif
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::operator CCallStackStatsGatherer_Standardized_t( void )
+{
+ return CCallStackStatsGatherer_Standardized_t( this, GetFunctionTable() );
+}
+
+template <class STATSTRUCT, size_t CAPTUREDCALLSTACKLENGTH, FN_GetCallStack STACKACQUISITIONFUNCTION, typename STATMUTEXHANDLER, template <typename T> class TEMPLATIZEDMEMORYALLOCATOR>
+CCallStackStatsGatherer_Standardized_t CCallStackStatsGatherer<STATSTRUCT, CAPTUREDCALLSTACKLENGTH, STACKACQUISITIONFUNCTION, STATMUTEXHANDLER, TEMPLATIZEDMEMORYALLOCATOR>::Standardized( void )
+{
+ return CCallStackStatsGatherer_Standardized_t( this, GetFunctionTable() );
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+class PLATFORM_CLASS CallStackStatStructDescFuncs
+{
+public:
+ //description file format
+ //1 byte version per entry. Assuming that the field will get more descriptive over time, reserving this now.
+ virtual size_t DescribeField( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) = 0;
+
+ enum MergeScript_Language
+ {
+ SSMSL_Squirrel, //Only support squirrel for now, theoretically expandable to any vscript supported language
+ };
+
+#if 0 //embedded script handling not ready yet
+ //this is expected to write a piece of script code into the body of a function that will merge two values of this type
+ //The function will have two parameters, "mergeTo", and "mergeFrom". Both are tables with your field defined by name
+ //So, an example to merge an integer count defined as "foo" in the stack struct would look like this "mergeTo.foo += mergeFrom.foo\n"
+ virtual size_t DescribeMergeOperation( MergeScript_Language scriptLanguage, uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength ) = 0;
+#endif
+
+ //reserve your description field versions here to avoid stomping others
+ enum DescribeFieldVersions_t
+ {
+ DFV_BasicStatStructFieldTypes_t, //Format: 1 byte BasicStatStructFieldTypes_t type, 4 byte field offset, null terminated string field name
+ };
+
+ const char *m_szFieldName;
+ size_t m_iFieldOffset;
+ CallStackStatStructDescFuncs *m_pNext; //needed for how the description macros are laid out. Couldn't figure out a way to store the static struct instances as a static array
+};
+
+enum StatStructDescription_LumpID
+{
+ SSDLID_UNKNOWN,
+ SSDLID_STATICINTERPRETER,
+ SSDLID_FIELDDESC,
+ SSDLID_EMBEDDEDSCRIPT,
+
+
+ SSDLID_COUNT,
+ SSDLID_FORCE_UINT32 = 0xFFFFFFFF,
+};
+
+enum BasicStatStructFieldTypes_t
+{
+ BSSFT_UNKNOWN,
+ BSSFT_BOOL,
+ BSSFT_INT8,
+ BSSFT_UINT8,
+ BSSFT_INT16,
+ BSSFT_UINT16,
+ BSSFT_INT32,
+ BSSFT_UINT32,
+ BSSFT_INT64,
+ BSSFT_UINT64,
+ BSSFT_FLOAT,
+ BSSFT_DOUBLE,
+ BSSFT_VECTOR2D,
+ BSSFT_VECTOR3D,
+ BSSFT_VECTOR4D,
+
+ BSSFT_COUNT,
+};
+
+#define BSSFT_INT (sizeof( int ) == sizeof( int32 ) ? BSSFT_INT32 : BSSFT_INT64)
+#define BSSFT_UINT (sizeof( unsigned int ) == sizeof( uint32 ) ? BSSFT_UINT32 : BSSFT_UINT64)
+#define BSSFT_SIZE_T (sizeof( size_t ) == sizeof( uint32 ) ? BSSFT_UINT32 : BSSFT_UINT64)
+
+enum BasicStatStructFieldCombineMethods_t
+{
+ BSSFCM_UNKNOWN,
+ BSSFCM_CUSTOM, //rely on some outside handler
+ BSSFCM_ADD, //add the values
+ //BSSFCM_SUBTRACT, //what would subtract even mean? which one from which?
+ BSSFCM_MAX, //keep max value
+ BSSFCM_MIN, //keep min value
+ BSSFCM_AND, // &= , Non-integer behavior undefined
+ BSSFCM_OR, // |= , Non-integer behavior undefined
+ BSSFCM_XOR, // ^= , Non-integer behavior undefined
+ /*BSSFCM_LIST, //keep a list of each value (probably complicated)*/
+
+ BSSFCM_COUNT,
+};
+
+class PLATFORM_CLASS BasicStatStructFieldDesc : public CallStackStatStructDescFuncs
+{
+public:
+ BasicStatStructFieldDesc( BasicStatStructFieldTypes_t type, BasicStatStructFieldCombineMethods_t combineMethod ) : m_Type(type), m_Combine(combineMethod) {};
+ size_t DescribeField( uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+#if 0 //embedded script handling not ready yet
+ size_t DescribeMergeOperation( MergeScript_Language scriptLanguage, uint8 *pDescribeWriteBuffer, size_t iDescribeMaxLength );
+#endif
+
+ BasicStatStructFieldTypes_t m_Type;
+ BasicStatStructFieldCombineMethods_t m_Combine;
+};
+
+
+
+
+
+
+
+//struct is locked in place while you're holding onto one of these. Get a base, then create one of these from it
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_AutoLock : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_AutoLock( CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> &copyFrom )
+ : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( copyFrom )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, true );
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, true );
+ this->m_pStruct = (STATSTRUCT *)this->m_Gatherer.pFunctionTable->pfn_GetEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex );
+ }
+
+ ~CCallStackStatsGatherer_StructAccessor_AutoLock( void )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, false );
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, false );
+ }
+
+ STATSTRUCT *operator->()
+ {
+ return this->m_pStruct;
+ }
+
+ STATSTRUCT *GetStruct( void ) //do not hold this pointer outside the lock period
+ {
+ return this->m_pStruct;
+ }
+
+protected:
+ STATSTRUCT *m_pStruct;
+};
+
+
+//struct is locked in place only between Lock() and paired Unlock() calls. Get a base, then create one of these from it.
+//It's safe to hold onto this for an extended period of time. The entry index is unchanging in the gatherer tree.
+template <class STATSTRUCT>
+class CCallStackStatsGatherer_StructAccessor_Manual : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>
+{
+public:
+ CCallStackStatsGatherer_StructAccessor_Manual( CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT> &copyFrom )
+ : CCallStackStatsGatherer_StructAccessor_Base<STATSTRUCT>( copyFrom ), m_pStruct( NULL )
+ { }
+
+ STATSTRUCT *operator->()
+ {
+ return this->m_pStruct; //NULL while entry is not locked.
+ }
+
+ STATSTRUCT *GetStruct( void ) //do not hold this pointer outside the lock period
+ {
+ return this->m_pStruct; //NULL while entry is not locked.
+ }
+
+ void Lock( void )
+ {
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, true );
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, true );
+ this->m_pStruct = (STATSTRUCT *)this->m_Gatherer.pFunctionTable->pfn_GetEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex );
+ }
+
+ void Unlock( void )
+ {
+ this->m_pStruct = NULL;
+ this->m_Gatherer.pFunctionTable->pfn_LockEntry( this->m_Gatherer.pGatherer, this->m_iEntryIndex, false );
+ this->m_Gatherer.pFunctionTable->pfn_ApplyTreeAccessLock( this->m_Gatherer.pGatherer, false );
+ }
+
+protected:
+ STATSTRUCT *m_pStruct;
+};
+
+
+
+
+
+class CCallStackStats_PushSubTree_AutoPop
+{
+public:
+ CCallStackStats_PushSubTree_AutoPop( const CCallStackStatsGatherer_Standardized_t &Parent, const CCallStackStatsGatherer_Standardized_t &Child, const CCallStackStorage &PushStack = CCallStackStorage() )
+ : m_PopFrom( Parent )
+ {
+ Parent.pFunctionTable->pfn_PushSubTree( Parent.pGatherer, Child, PushStack );
+ }
+ ~CCallStackStats_PushSubTree_AutoPop( void )
+ {
+ m_PopFrom.PopSubTree();
+ }
+
+ CCallStackStatsGatherer_Standardized_t m_PopFrom;
+};
+
+
+#endif //#ifndef TIER0_STACKTOOLS_H
diff --git a/external/vpc/public/tier0/stacktools.h b/external/vpc/public/tier0/stacktools.h
new file mode 100644
index 0000000..c356b8c
--- /dev/null
+++ b/external/vpc/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 &copyFrom )
+ {
+ 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/external/vpc/public/tier0/threadtools.h b/external/vpc/public/tier0/threadtools.h
new file mode 100644
index 0000000..458675a
--- /dev/null
+++ b/external/vpc/public/tier0/threadtools.h
@@ -0,0 +1,2402 @@
+//========== Copyright 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose: A collection of utility classes to simplify thread handling, and
+// as much as possible contain portability problems. Here avoiding
+// including windows.h.
+//
+//=============================================================================
+
+#ifndef THREADTOOLS_H
+#define THREADTOOLS_H
+
+#include <limits.h>
+
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+
+#if defined( POSIX ) && !defined( _PS3 ) && !defined( _X360 )
+#include <pthread.h>
+#include <errno.h>
+#define WAIT_OBJECT_0 0
+#define WAIT_TIMEOUT 0x00000102
+#define WAIT_FAILED -1
+#define THREAD_PRIORITY_HIGHEST 2
+#endif
+
+#if defined( _PS3 )
+#include <sys/ppu_thread.h>
+#include <sys/synchronization.h>
+#include <cell/atomic.h>
+#include <sys/timer.h>
+#endif
+
+#ifdef OSX
+// Add some missing defines
+#define PTHREAD_MUTEX_TIMED_NP PTHREAD_MUTEX_NORMAL
+#define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
+#define PTHREAD_MUTEX_ERRORCHECK_NP PTHREAD_MUTEX_ERRORCHECK
+#define PTHREAD_MUTEX_ADAPTIVE_NP 3
+#endif
+
+#ifdef _PS3
+#define PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE ( 256 * 1024 )
+#endif
+
+
+#if defined( _WIN32 )
+#pragma once
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
+#ifdef COMPILER_MSVC64
+#include <intrin.h>
+#endif
+
+// #define THREAD_PROFILER 1
+
+#define THREAD_MUTEX_TRACING_SUPPORTED
+#if defined(_WIN32) && defined(_DEBUG)
+#define THREAD_MUTEX_TRACING_ENABLED
+#endif
+
+#ifdef _WIN32
+typedef void *HANDLE;
+#endif
+
+// maximum number of threads that can wait on one object
+#define CTHREADEVENT_MAX_WAITING_THREADS 4
+
+#if (defined( PLATFORM_WINDOWS_PC ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT )
+//Thread parent stack trace linkage requires ALL executing binaries to disable frame pointer omission to operate speedily/successfully. (/Oy-) "vpc /nofpo"
+#define THREAD_PARENT_STACK_TRACE_SUPPORTED 1 //uncomment to support joining the root of a thread's stack trace to its parent's at time of invocation. Must also set ENABLE_THREAD_PARENT_STACK_TRACING in stacktools.h
+#endif
+
+#if defined( THREAD_PARENT_STACK_TRACE_SUPPORTED )
+#include "tier0/stacktools.h"
+# if defined( ENABLE_THREAD_PARENT_STACK_TRACING ) //stacktools.h opted in
+# define THREAD_PARENT_STACK_TRACE_ENABLED 1 //both threadtools.h and stacktools.h have opted into the feature, enable it
+# endif
+#endif
+
+extern bool gbCheckNotMultithreaded;
+
+#ifdef _PS3
+
+#define USE_INTRINSIC_INTERLOCKED
+
+#define CHECK_NOT_MULTITHREADED() \
+{ \
+ static int init = 0; \
+ static sys_ppu_thread_t threadIDPrev; \
+ \
+ if (!init) \
+ { \
+ sys_ppu_thread_get_id(&threadIDPrev); \
+ init = 1; \
+ } \
+ else if (gbCheckNotMultithreaded) \
+ { \
+ sys_ppu_thread_t threadID; \
+ sys_ppu_thread_get_id(&threadID); \
+ if (threadID != threadIDPrev) \
+ { \
+ printf("CHECK_NOT_MULTITHREADED: prev thread = %x, cur thread = %x\n", \
+ (uint)threadIDPrev, (uint)threadID); \
+ *(int*)0 = 0; \
+ } \
+ } \
+}
+
+#else
+ #define CHECK_NOT_MULTITHREADED()
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define MAX_THREADS_SUPPORTED 16
+#else
+#define MAX_THREADS_SUPPORTED 32
+#endif
+
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+const unsigned TT_INFINITE = 0xffffffff;
+
+#ifdef PLATFORM_64BITS
+typedef uint64 ThreadId_t;
+#else
+typedef uint32 ThreadId_t;
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Simple thread creation. Differs from VCR mode/CreateThread/_beginthreadex
+// in that it accepts a standard C function rather than compiler specific one.
+//
+//-----------------------------------------------------------------------------
+#ifdef COMPILER_SNC
+typedef uint64 ThreadHandle_t;
+#else // COMPILER_SNC
+FORWARD_DECLARE_HANDLE( ThreadHandle_t );
+#endif // !COMPILER_SNC
+typedef uintp (*ThreadFunc_t)( void *pParam );
+
+#if defined( _PS3 )
+PLATFORM_OVERLOAD ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, ThreadId_t *pID, unsigned stackSize = 0x10000 /*64*/ );
+PLATFORM_INTERFACE ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, unsigned stackSize = 0x10000 /*64*/ );
+#else //_PS3
+PLATFORM_OVERLOAD ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, ThreadId_t *pID, unsigned stackSize = 0 );
+PLATFORM_INTERFACE ThreadHandle_t CreateSimpleThread( ThreadFunc_t, void *pParam, unsigned stackSize = 0 );
+#endif //_PS3
+PLATFORM_INTERFACE bool ReleaseThreadHandle( ThreadHandle_t );
+
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE void ThreadSleep(unsigned duration = 0);
+PLATFORM_INTERFACE ThreadId_t ThreadGetCurrentId();
+PLATFORM_INTERFACE ThreadHandle_t ThreadGetCurrentHandle();
+PLATFORM_INTERFACE int ThreadGetPriority( ThreadHandle_t hThread = NULL );
+PLATFORM_INTERFACE bool ThreadSetPriority( ThreadHandle_t hThread, int priority );
+inline bool ThreadSetPriority( int priority ) { return ThreadSetPriority( NULL, priority ); }
+#ifndef _X360
+PLATFORM_INTERFACE bool ThreadInMainThread();
+PLATFORM_INTERFACE void DeclareCurrentThreadIsMainThread();
+#else
+PLATFORM_INTERFACE byte *g_pBaseMainStack;
+PLATFORM_INTERFACE byte *g_pLimitMainStack;
+inline bool ThreadInMainThread()
+{
+ byte b;
+ byte *p = &b;
+ return ( p < g_pBaseMainStack && p >= g_pLimitMainStack );
+}
+#endif
+
+// NOTE: ThreadedLoadLibraryFunc_t needs to return the sleep time in milliseconds or TT_INFINITE
+typedef int (*ThreadedLoadLibraryFunc_t)();
+PLATFORM_INTERFACE void SetThreadedLoadLibraryFunc( ThreadedLoadLibraryFunc_t func );
+PLATFORM_INTERFACE ThreadedLoadLibraryFunc_t GetThreadedLoadLibraryFunc();
+
+#if defined( PLATFORM_WINDOWS_PC32 )
+DLL_IMPORT unsigned long STDCALL GetCurrentThreadId();
+#define ThreadGetCurrentId GetCurrentThreadId
+#endif
+
+inline void ThreadPause()
+{
+#if defined( COMPILER_PS3 )
+ __db16cyc();
+#elif defined( COMPILER_GCC )
+ __asm __volatile( "pause" );
+#elif defined ( COMPILER_MSVC64 )
+ _mm_pause();
+#elif defined( COMPILER_MSVC32 )
+ __asm pause;
+#elif defined( COMPILER_MSVCX360 )
+ YieldProcessor();
+ __asm { or r0,r0,r0 }
+ YieldProcessor();
+ __asm { or r1,r1,r1 }
+#else
+#error "implement me"
+#endif
+}
+
+PLATFORM_INTERFACE bool ThreadJoin( ThreadHandle_t, unsigned timeout = TT_INFINITE );
+
+PLATFORM_INTERFACE void ThreadSetDebugName( ThreadHandle_t hThread, const char *pszName );
+inline void ThreadSetDebugName( const char *pszName ) { ThreadSetDebugName( NULL, pszName ); }
+
+PLATFORM_INTERFACE void ThreadSetAffinity( ThreadHandle_t hThread, int nAffinityMask );
+
+
+//-----------------------------------------------------------------------------
+//
+// Interlock methods. These perform very fast atomic thread
+// safe operations. These are especially relevant in a multi-core setting.
+//
+//-----------------------------------------------------------------------------
+
+#ifdef _WIN32
+#define NOINLINE
+#elif defined( _PS3 )
+#define NOINLINE __attribute__ ((noinline))
+#elif defined(POSIX)
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+#if defined( _X360 ) || defined( _PS3 )
+#define ThreadMemoryBarrier() __lwsync()
+#else
+#define ThreadMemoryBarrier() ((void)0)
+#endif
+
+#if defined( _LINUX ) || defined( _OSX )
+#define USE_INTRINSIC_INTERLOCKED
+// linux implementation
+inline int32 ThreadInterlockedIncrement( int32 volatile *p )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, 1 ) + 1;
+}
+
+inline int32 ThreadInterlockedDecrement( int32 volatile *p )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, -1 ) - 1;
+}
+
+inline int32 ThreadInterlockedExchange( int32 volatile *p, int32 value )
+{
+ Assert( (size_t)p % 4 == 0 );
+ int32 nRet;
+
+ // Note: The LOCK instruction prefix is assumed on the XCHG instruction and GCC gets very confused on the Mac when we use it.
+ __asm __volatile(
+ "xchgl %2,(%1)"
+ : "=r" (nRet)
+ : "r" (p), "0" (value)
+ : "memory");
+ return nRet;
+}
+
+inline int32 ThreadInterlockedExchangeAdd( int32 volatile *p, int32 value )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_fetch_and_add( p, value );
+}
+inline int32 ThreadInterlockedCompareExchange( int32 volatile *p, int32 value, int32 comperand )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_val_compare_and_swap( p, comperand, value );
+}
+
+
+inline bool ThreadInterlockedAssignIf( int32 volatile *p, int32 value, int32 comperand )
+{
+ Assert( (size_t)p % 4 == 0 );
+ return __sync_bool_compare_and_swap( p, comperand, value );
+}
+
+#elif ( defined( COMPILER_MSVC32 ) && ( _MSC_VER >= 1310 ) )
+// windows 32 implemnetation using compiler intrinsics
+#define USE_INTRINSIC_INTERLOCKED
+
+extern "C"
+{
+ long __cdecl _InterlockedIncrement(volatile long*);
+ long __cdecl _InterlockedDecrement(volatile long*);
+ long __cdecl _InterlockedExchange(volatile long*, long);
+ long __cdecl _InterlockedExchangeAdd(volatile long*, long);
+ long __cdecl _InterlockedCompareExchange(volatile long*, long, long);
+}
+
+#pragma intrinsic( _InterlockedCompareExchange )
+#pragma intrinsic( _InterlockedDecrement )
+#pragma intrinsic( _InterlockedExchange )
+#pragma intrinsic( _InterlockedExchangeAdd )
+#pragma intrinsic( _InterlockedIncrement )
+
+inline int32 ThreadInterlockedIncrement( int32 volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( (volatile long*)p ); }
+inline int32 ThreadInterlockedDecrement( int32 volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( (volatile long*)p ); }
+inline int32 ThreadInterlockedExchange( int32 volatile *p, int32 value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( (volatile long*)p, value ); }
+inline int32 ThreadInterlockedExchangeAdd( int32 volatile *p, int32 value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( (volatile long*)p, value ); }
+inline int32 ThreadInterlockedCompareExchange( int32 volatile *p, int32 value, int32 comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( (volatile long*)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( int32 volatile *p, int32 value, int32 comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( (volatile long*)p, value, comperand ) == comperand ); }
+#elif defined( _PS3 )
+PLATFORM_INTERFACE inline int32 ThreadInterlockedIncrement( int32 volatile * ea ) { return cellAtomicIncr32( (uint32_t*)ea ) + 1; }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedDecrement( int32 volatile * ea ) { return cellAtomicDecr32( (uint32_t*)ea ) - 1; }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedExchange( int32 volatile * ea, int32 value ) { return cellAtomicStore32( ( uint32_t* )ea, value); }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedExchangeAdd( int32 volatile * ea, int32 value ) { return cellAtomicAdd32( ( uint32_t* )ea, value ); }
+PLATFORM_INTERFACE inline int32 ThreadInterlockedCompareExchange( int32 volatile * ea, int32 value, int32 comperand ) { return cellAtomicCompareAndSwap32( (uint32_t*)ea, comperand, value ) ; }
+PLATFORM_INTERFACE inline bool ThreadInterlockedAssignIf( int32 volatile * ea, int32 value, int32 comperand ) { return ( cellAtomicCompareAndSwap32( (uint32_t*)ea, comperand, value ) == ( uint32_t ) comperand ); }
+
+PLATFORM_INTERFACE inline int64 ThreadInterlockedCompareExchange64( int64 volatile *pDest, int64 value, int64 comperand ) { return cellAtomicCompareAndSwap64( ( uint64_t* ) pDest, comperand, value ); }
+PLATFORM_INTERFACE inline bool ThreadInterlockedAssignIf64( volatile int64 *pDest, int64 value, int64 comperand ) { return ( cellAtomicCompareAndSwap64( ( uint64_t* ) pDest, comperand, value ) == ( uint64_t ) comperand ); }
+
+#elif defined( _X360 )
+#define TO_INTERLOCK_PARAM(p) ((volatile long *)p)
+#define TO_INTERLOCK_PTR_PARAM(p) ((void **)p)
+FORCEINLINE int32 ThreadInterlockedIncrement( int32 volatile *pDest ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedIncrement( TO_INTERLOCK_PARAM(pDest) ); }
+FORCEINLINE int32 ThreadInterlockedDecrement( int32 volatile *pDest ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedDecrement( TO_INTERLOCK_PARAM(pDest) ); }
+FORCEINLINE int32 ThreadInterlockedExchange( int32 volatile *pDest, int32 value ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedExchange( TO_INTERLOCK_PARAM(pDest), value ); }
+FORCEINLINE int32 ThreadInterlockedExchangeAdd( int32 volatile *pDest, int32 value ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedExchangeAdd( TO_INTERLOCK_PARAM(pDest), value ); }
+FORCEINLINE int32 ThreadInterlockedCompareExchange( int32 volatile *pDest, int32 value, int32 comperand ) { Assert( (size_t)pDest % 4 == 0 ); return InterlockedCompareExchange( TO_INTERLOCK_PARAM(pDest), value, comperand ); }
+FORCEINLINE bool ThreadInterlockedAssignIf( int32 volatile *pDest, int32 value, int32 comperand ) { Assert( (size_t)pDest % 4 == 0 ); return ( InterlockedCompareExchange( TO_INTERLOCK_PARAM(pDest), value, comperand ) == comperand ); }
+#else
+// non 32-bit windows and 360 implementation
+PLATFORM_INTERFACE int32 ThreadInterlockedIncrement( int32 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedDecrement( int32 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedExchange( int32 volatile *, int32 value ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedExchangeAdd( int32 volatile *, int32 value ) NOINLINE;
+PLATFORM_INTERFACE int32 ThreadInterlockedCompareExchange( int32 volatile *, int32 value, int32 comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf( int32 volatile *, int32 value, int32 comperand ) NOINLINE;
+#endif
+
+
+#if defined( USE_INTRINSIC_INTERLOCKED ) && !defined( PLATFORM_64BITS )
+#define TIPTR()
+inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)( ( intp )ThreadInterlockedExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value) ) ); }
+inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)( ( intp )ThreadInterlockedCompareExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value), reinterpret_cast<intp>(comperand) ) ); }
+inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( ThreadInterlockedCompareExchange( reinterpret_cast<intp volatile *>(p), reinterpret_cast<intp>(value), reinterpret_cast<intp>(comperand) ) == reinterpret_cast<intp>(comperand) ); }
+#else
+PLATFORM_INTERFACE void *ThreadInterlockedExchangePointer( void * volatile *, void *value ) NOINLINE;
+PLATFORM_INTERFACE void *ThreadInterlockedCompareExchangePointer( void * volatile *, void *value, void *comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignPointerIf( void * volatile *, void *value, void *comperand ) NOINLINE;
+#endif
+
+
+inline unsigned ThreadInterlockedExchangeSubtract( int32 volatile *p, int32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, -value ); }
+
+inline void const *ThreadInterlockedExchangePointerToConst( void const * volatile *p, void const *value ) { return ThreadInterlockedExchangePointer( const_cast < void * volatile * > ( p ), const_cast < void * > ( value ) ); }
+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 ) ); }
+
+
+#ifndef _PS3
+PLATFORM_INTERFACE int64 ThreadInterlockedCompareExchange64( int64 volatile *, int64 value, int64 comperand ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf64( volatile int64 *pDest, int64 value, int64 comperand ) NOINLINE;
+#endif
+
+PLATFORM_INTERFACE int64 ThreadInterlockedExchange64( int64 volatile *, int64 value ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedIncrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedDecrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedExchangeAdd64( int64 volatile *, int64 value ) NOINLINE;
+
+inline unsigned ThreadInterlockedExchangeSubtract( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+
+inline unsigned ThreadInterlockedIncrement( uint32 volatile *p ) { return ThreadInterlockedIncrement( (int32 volatile *)p ); }
+inline unsigned ThreadInterlockedDecrement( uint32 volatile *p ) { return ThreadInterlockedDecrement( (int32 volatile *)p ); }
+inline unsigned ThreadInterlockedExchange( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchange( (int32 volatile *)p, value ); }
+inline unsigned ThreadInterlockedExchangeAdd( uint32 volatile *p, uint32 value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+inline unsigned ThreadInterlockedCompareExchange( uint32 volatile *p, uint32 value, uint32 comperand ) { return ThreadInterlockedCompareExchange( (int32 volatile *)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( uint32 volatile *p, uint32 value, uint32 comperand ) { return ThreadInterlockedAssignIf( (int32 volatile *)p, value, comperand ); }
+
+//inline int ThreadInterlockedExchangeSubtract( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedIncrement( int volatile *p ) { return ThreadInterlockedIncrement( (int32 volatile *)p ); }
+//inline int ThreadInterlockedDecrement( int volatile *p ) { return ThreadInterlockedDecrement( (int32 volatile *)p ); }
+//inline int ThreadInterlockedExchange( int volatile *p, int value ) { return ThreadInterlockedExchange( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedExchangeAdd( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (int32 volatile *)p, value ); }
+//inline int ThreadInterlockedCompareExchange( int volatile *p, int value, int comperand ) { return ThreadInterlockedCompareExchange( (int32 volatile *)p, value, comperand ); }
+//inline bool ThreadInterlockedAssignIf( int volatile *p, int value, int comperand ) { return ThreadInterlockedAssignIf( (int32 volatile *)p, value, comperand ); }
+
+
+//-----------------------------------------------------------------------------
+// Access to VTune thread profiling
+//-----------------------------------------------------------------------------
+#if defined(_WIN32) && defined(THREAD_PROFILER)
+PLATFORM_INTERFACE void ThreadNotifySyncPrepare(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncCancel(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncAcquired(void *p);
+PLATFORM_INTERFACE void ThreadNotifySyncReleasing(void *p);
+#else
+#define ThreadNotifySyncPrepare(p) ((void)0)
+#define ThreadNotifySyncCancel(p) ((void)0)
+#define ThreadNotifySyncAcquired(p) ((void)0)
+#define ThreadNotifySyncReleasing(p) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+// Encapsulation of a thread local datum (needed because THREAD_LOCAL doesn't
+// work in a DLL loaded with LoadLibrary()
+//-----------------------------------------------------------------------------
+
+#ifndef NO_THREAD_LOCAL
+
+#if defined( _PS3 )
+// linux totally supports compiler thread locals, even across dll's.
+#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1
+#define CTHREADLOCALUSEERROR PS3_ELF_EXPORTED_THREADLOCAL PS3_ELF_EXPORTED_THREADLOCAL PS3_ELF_EXPORTED_THREADLOCAL
+#define CTHREADLOCALINTEGER( typ ) CTHREADLOCALUSEERROR int
+#define CTHREADLOCALINT CTHREADLOCALUSEERROR int
+#define CTHREADLOCALPTR( typ ) CTHREADLOCALUSEERROR typ *
+#define CTHREADLOCAL( typ ) CTHREADLOCALUSEERROR typ
+#define GETLOCAL( x ) ( x )
+#endif
+
+
+#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 )
+#ifndef TIER0_DLL_EXPORT
+DLL_IMPORT __thread int g_nThreadID;
+#endif
+#endif
+
+#if defined(WIN32) || defined(OSX)
+#ifndef __AFXTLS_H__ // not compatible with some Windows headers
+
+#define CTHREADLOCALINT GenericThreadLocals::CThreadLocalInt<int>
+#define CTHREADLOCALINTEGER( typ ) GenericThreadLocals::CThreadLocalInt<typ>
+#define CTHREADLOCALPTR( typ ) GenericThreadLocals::CThreadLocalPtr<typ>
+#define CTHREADLOCAL( typ ) GenericThreadLocals::CThreadLocal<typ>
+#define GETLOCAL( x ) ( x.Get() )
+
+
+namespace GenericThreadLocals
+{
+ // a (not so efficient) implementation of thread locals for compilers without full support (i.e. visual c).
+ // don't use this explicity - instead, use the CTHREADxxx macros above.
+
+ class PLATFORM_CLASS CThreadLocalBase
+ {
+public:
+ CThreadLocalBase();
+ ~CThreadLocalBase();
+
+ void * Get() const;
+ void Set(void *);
+
+private:
+#if defined(POSIX) && !defined( _GAMECONSOLE )
+ pthread_key_t m_index;
+#else
+ uint32 m_index;
+#endif
+ };
+
+ //---------------------------------------------------------
+
+ template <class T>
+ class CThreadLocal : public CThreadLocalBase
+ {
+ public:
+ CThreadLocal()
+ {
+#ifdef PLATFORM_64BITS
+ COMPILE_TIME_ASSERT( sizeof(T) <= sizeof(void *) );
+#else
+ COMPILE_TIME_ASSERT( sizeof(T) == sizeof(void *) );
+#endif
+ }
+
+ void operator=( T i ) { Set( i ); }
+
+ T Get() const
+ {
+#ifdef PLATFORM_64BITS
+ void *pData = CThreadLocalBase::Get();
+ return *reinterpret_cast<T*>( &pData );
+#else
+ #ifdef COMPILER_MSVC
+ #pragma warning ( disable : 4311 )
+ #endif
+ return reinterpret_cast<T>( CThreadLocalBase::Get() );
+ #ifdef COMPILER_MSVC
+ #pragma warning ( default : 4311 )
+ #endif
+#endif
+ }
+
+ void Set(T val)
+ {
+#ifdef PLATFORM_64BITS
+ void* pData = 0;
+ *reinterpret_cast<T*>( &pData ) = val;
+ CThreadLocalBase::Set( pData );
+#else
+ #ifdef COMPILER_MSVC
+ #pragma warning ( disable : 4312 )
+ #endif
+ CThreadLocalBase::Set( reinterpret_cast<void *>(val) );
+ #ifdef COMPILER_MSVC
+ #pragma warning ( default : 4312 )
+ #endif
+#endif
+ }
+ };
+
+
+ //---------------------------------------------------------
+
+ template <class T = int32>
+ class CThreadLocalInt : public CThreadLocal<T>
+ {
+ public:
+ operator const T() const { return this->Get(); }
+ int operator=( T i ) { this->Set( i ); return i; }
+
+ T operator++() { T i = this->Get(); this->Set( ++i ); return i; }
+ T operator++(int) { T i = this->Get(); this->Set( i + 1 ); return i; }
+
+ T operator--() { T i = this->Get(); this->Set( --i ); return i; }
+ T operator--(int) { T i = this->Get(); this->Set( i - 1 ); return i; }
+
+ inline CThreadLocalInt( ) { }
+ inline CThreadLocalInt( const T &initialvalue )
+ {
+ this->Set( initialvalue );
+ }
+ };
+
+
+ //---------------------------------------------------------
+
+ template <class T>
+ class CThreadLocalPtr : private CThreadLocalBase
+ {
+ public:
+ CThreadLocalPtr() {}
+
+ operator const void *() const { return (const T *)Get(); }
+ operator void *() { return (T *)Get(); }
+
+ operator const T *() const { return (const T *)Get(); }
+ operator const T *() { return (const T *)Get(); }
+ operator T *() { return (T *)Get(); }
+
+ T * operator=( T *p ) { Set( p ); return p; }
+
+ bool operator !() const { return (!Get()); }
+ bool operator!=( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() != NULL); }
+ bool operator==( int i ) const { AssertMsg( i == 0, "Only NULL allowed on integer compare" ); return (Get() == NULL); }
+ bool operator==( const void *p ) const { return (Get() == p); }
+ bool operator!=( const void *p ) const { return (Get() != p); }
+ bool operator==( const T *p ) const { return operator==((const void*)p); }
+ bool operator!=( const T *p ) const { return operator!=((const void*)p); }
+
+ T * operator->() { return (T *)Get(); }
+ T & operator *() { return *((T *)Get()); }
+
+ const T * operator->() const { return (const T *)Get(); }
+ const T & operator *() const { return *((const T *)Get()); }
+
+ const T & operator[]( int i ) const { return *((const T *)Get() + i); }
+ T & operator[]( int i ) { return *((T *)Get() + i); }
+
+ private:
+ // Disallowed operations
+ CThreadLocalPtr( T *pFrom );
+ CThreadLocalPtr( const CThreadLocalPtr<T> &from );
+ T **operator &();
+ T * const *operator &() const;
+ void operator=( const CThreadLocalPtr<T> &from );
+ bool operator==( const CThreadLocalPtr<T> &p ) const;
+ bool operator!=( const CThreadLocalPtr<T> &p ) const;
+ };
+}
+
+#ifdef _OSX
+PLATFORM_INTERFACE GenericThreadLocals::CThreadLocalInt<int> g_nThreadID;
+#else // _OSX
+#ifndef TIER0_DLL_EXPORT
+
+#ifndef _PS3
+extern GenericThreadLocals::CThreadLocalInt<int> g_nThreadID;
+#endif // !_PS3
+
+#endif // TIER0_DLL_EXPORT
+#endif // _OSX
+
+#endif /// afx32
+#endif //__win32
+
+#endif // NO_THREAD_LOCAL
+
+//-----------------------------------------------------------------------------
+//
+// A super-fast thread-safe integer A simple class encapsulating the notion of an
+// atomic integer used across threads that uses the built in and faster
+// "interlocked" functionality rather than a full-blown mutex. Useful for simple
+// things like reference counts, etc.
+//
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CInterlockedIntT
+{
+public:
+ CInterlockedIntT() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T) == sizeof(int32) ); }
+ CInterlockedIntT( T value ) : m_value( value ) {}
+
+ T operator()( void ) const { return m_value; }
+ operator T() const { return m_value; }
+
+ bool operator!() const { return ( m_value == 0 ); }
+ bool operator==( T rhs ) const { return ( m_value == rhs ); }
+ bool operator!=( T rhs ) const { return ( m_value != rhs ); }
+
+ T operator++() { return (T)ThreadInterlockedIncrement( (int32 *)&m_value ); }
+ T operator++(int) { return operator++() - 1; }
+
+ T operator--() { return (T)ThreadInterlockedDecrement( (int32 *)&m_value ); }
+ T operator--(int) { return operator--() + 1; }
+
+ bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (int32 *)&m_value, (int32)newValue, (int32)conditionValue ); }
+
+ T operator=( T newValue ) { ThreadInterlockedExchange((int32 *)&m_value, newValue); return m_value; }
+
+ // Atomic add is like += except it returns the previous value as its return value
+ T AtomicAdd( T add ) { return (T)ThreadInterlockedExchangeAdd( (int32 *)&m_value, (int32)add ); }
+
+ void operator+=( T add ) { ThreadInterlockedExchangeAdd( (int32 *)&m_value, (int32)add ); }
+ void operator-=( T subtract ) { operator+=( -subtract ); }
+ void operator*=( T multiplier ) {
+ T original, result;
+ do
+ {
+ original = m_value;
+ result = original * multiplier;
+ } while ( !AssignIf( original, result ) );
+ }
+ void operator/=( T divisor ) {
+ T original, result;
+ do
+ {
+ original = m_value;
+ result = original / divisor;
+ } while ( !AssignIf( original, result ) );
+ }
+
+ T operator+( T rhs ) const { return m_value + rhs; }
+ T operator-( T rhs ) const { return m_value - rhs; }
+
+private:
+ volatile T m_value;
+};
+
+typedef CInterlockedIntT<int> CInterlockedInt;
+typedef CInterlockedIntT<unsigned> CInterlockedUInt;
+
+//-----------------------------------------------------------------------------
+
+template <typename T>
+class CInterlockedPtr
+{
+public:
+ CInterlockedPtr() : m_value( 0 ) { COMPILE_TIME_ASSERT( sizeof(T *) == sizeof(int32) ); /* Will need to rework operator+= for 64 bit */ }
+ CInterlockedPtr( T *value ) : m_value( value ) {}
+
+ operator T *() const { return m_value; }
+
+ bool operator!() const { return ( m_value == 0 ); }
+ bool operator==( T *rhs ) const { return ( m_value == rhs ); }
+ bool operator!=( T *rhs ) const { return ( m_value != rhs ); }
+
+ T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, sizeof(T) )) + 1; }
+ T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, sizeof(T) ); }
+
+ T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, -sizeof(T) )) - 1; }
+ T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (int32 *)&m_value, -sizeof(T) ); }
+
+ bool AssignIf( T *conditionValue, T *newValue ) { return ThreadInterlockedAssignPointerToConstIf( (void const **) &m_value, (void const *) newValue, (void const *) conditionValue ); }
+
+ T *operator=( T *newValue ) { ThreadInterlockedExchangePointerToConst( (void const **) &m_value, (void const *) newValue ); return newValue; }
+
+ void operator+=( int add ) { ThreadInterlockedExchangeAdd( (int32 *)&m_value, add * sizeof(T) ); }
+ void operator-=( int subtract ) { operator+=( -subtract ); }
+
+ // Atomic add is like += except it returns the previous value as its return value
+ T *AtomicAdd( int add ) { return ( T * ) ThreadInterlockedExchangeAdd( (int32 *)&m_value, add * sizeof(T) ); }
+
+ T *operator+( int rhs ) const { return m_value + rhs; }
+ T *operator-( int rhs ) const { return m_value - rhs; }
+ T *operator+( unsigned rhs ) const { return m_value + rhs; }
+ T *operator-( unsigned rhs ) const { return m_value - rhs; }
+ size_t operator-( T *p ) const { return m_value - p; }
+ size_t operator-( const CInterlockedPtr<T> &p ) const { return m_value - p.m_value; }
+
+private:
+ T * volatile m_value;
+};
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Platform independent for critical sections management
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadMutex
+{
+public:
+ CThreadMutex();
+ ~CThreadMutex();
+
+ //------------------------------------------------------
+ // Mutex acquisition/release. Const intentionally defeated.
+ //------------------------------------------------------
+ void Lock();
+ void Lock() const { (const_cast<CThreadMutex *>(this))->Lock(); }
+ void Unlock();
+ void Unlock() const { (const_cast<CThreadMutex *>(this))->Unlock(); }
+
+ bool TryLock();
+ bool TryLock() const { return (const_cast<CThreadMutex *>(this))->TryLock(); }
+
+ void LockSilent(); // A Lock() operation which never spews. Required by the logging system to prevent badness.
+ void UnlockSilent(); // An Unlock() operation which never spews. Required by the logging system to prevent badness.
+
+ //------------------------------------------------------
+ // Use this to make deadlocks easier to track by asserting
+ // when it is expected that the current thread owns the mutex
+ //------------------------------------------------------
+ bool AssertOwnedByCurrentThread();
+
+ //------------------------------------------------------
+ // Enable tracing to track deadlock problems
+ //------------------------------------------------------
+ void SetTrace( bool );
+
+private:
+ // Disallow copying
+ CThreadMutex( const CThreadMutex & );
+ CThreadMutex &operator=( const CThreadMutex & );
+
+#if defined( _WIN32 )
+ // Efficient solution to breaking the windows.h dependency, invariant is tested.
+#ifdef _WIN64
+ #define TT_SIZEOF_CRITICALSECTION 40
+#else
+#ifndef _X360
+ #define TT_SIZEOF_CRITICALSECTION 24
+#else
+ #define TT_SIZEOF_CRITICALSECTION 28
+#endif // !_X360
+#endif // _WIN64
+ byte m_CriticalSection[TT_SIZEOF_CRITICALSECTION];
+#elif defined( _PS3 )
+ sys_mutex_t m_Mutex;
+#elif defined(POSIX)
+ pthread_mutex_t m_Mutex;
+ pthread_mutexattr_t m_Attr;
+#else
+#error
+#endif
+
+#ifdef THREAD_MUTEX_TRACING_SUPPORTED
+ // Debugging (always herge to allow mixed debug/release builds w/o changing size)
+ uint m_currentOwnerID;
+ uint16 m_lockCount;
+ bool m_bTrace;
+#endif
+};
+
+//-----------------------------------------------------------------------------
+//
+// An alternative mutex that is useful for cases when thread contention is
+// rare, but a mutex is required. Instances should be declared volatile.
+// Sleep of 0 may not be sufficient to keep high priority threads from starving
+// lesser threads. This class is not a suitable replacement for a critical
+// section if the resource contention is high.
+//
+//-----------------------------------------------------------------------------
+
+#if !defined(THREAD_PROFILER)
+
+class CThreadFastMutex
+{
+public:
+ CThreadFastMutex()
+ : m_ownerID( 0 ),
+ m_depth( 0 )
+ {
+ }
+
+private:
+ FORCEINLINE bool TryLockInline( const uint32 threadId ) volatile
+ {
+ if ( threadId != m_ownerID && !ThreadInterlockedAssignIf( (volatile int32 *)&m_ownerID, (int32)threadId, 0 ) )
+ return false;
+
+ ThreadMemoryBarrier();
+ ++m_depth;
+ return true;
+ }
+
+ bool TryLock( const uint32 threadId ) volatile
+ {
+ return TryLockInline( threadId );
+ }
+
+ PLATFORM_CLASS void Lock( const uint32 threadId, unsigned nSpinSleepTime ) volatile;
+
+public:
+ bool TryLock() volatile
+ {
+#ifdef _DEBUG
+ if ( m_depth == INT_MAX )
+ DebuggerBreak();
+
+ if ( m_depth < 0 )
+ DebuggerBreak();
+#endif
+ return TryLockInline( ThreadGetCurrentId() );
+ }
+
+#ifndef _DEBUG
+ FORCEINLINE
+#endif
+ void Lock( unsigned int nSpinSleepTime = 0 ) volatile
+ {
+ const uint32 threadId = ThreadGetCurrentId();
+
+ if ( !TryLockInline( threadId ) )
+ {
+ ThreadPause();
+ Lock( threadId, nSpinSleepTime );
+ }
+#ifdef _DEBUG
+ if ( m_ownerID != ThreadGetCurrentId() )
+ DebuggerBreak();
+
+ if ( m_depth == INT_MAX )
+ DebuggerBreak();
+
+ if ( m_depth < 0 )
+ DebuggerBreak();
+#endif
+ }
+
+#ifndef _DEBUG
+ FORCEINLINE
+#endif
+ void Unlock() volatile
+ {
+#ifdef _DEBUG
+ if ( m_ownerID != ThreadGetCurrentId() )
+ DebuggerBreak();
+
+ if ( m_depth <= 0 )
+ DebuggerBreak();
+#endif
+
+ --m_depth;
+ if ( !m_depth )
+ {
+ ThreadMemoryBarrier();
+ ThreadInterlockedExchange( &m_ownerID, 0 );
+ }
+ }
+
+ bool TryLock() const volatile { return (const_cast<CThreadFastMutex *>(this))->TryLock(); }
+ void Lock(unsigned nSpinSleepTime = 0 ) const volatile { (const_cast<CThreadFastMutex *>(this))->Lock( nSpinSleepTime ); }
+ void Unlock() const volatile { (const_cast<CThreadFastMutex *>(this))->Unlock(); }
+
+ // To match regular CThreadMutex:
+ bool AssertOwnedByCurrentThread() { return true; }
+ void SetTrace( bool ) {}
+
+ uint32 GetOwnerId() const { return m_ownerID; }
+ int GetDepth() const { return m_depth; }
+private:
+ volatile uint32 m_ownerID;
+ int m_depth;
+};
+
+class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex
+{
+public:
+ CAlignedThreadFastMutex()
+ {
+ Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 );
+ }
+
+private:
+ uint8 pad[128-sizeof(CThreadFastMutex)];
+};
+
+#else
+#ifdef _PS3
+
+class CThreadFastMutex
+{
+public:
+ CThreadFastMutex();
+ ~CThreadFastMutex();
+
+ //------------------------------------------------------
+ // Mutex acquisition/release. Const intentionally defeated.
+ //------------------------------------------------------
+ void Lock();
+ void Lock() const { (const_cast<CThreadFastMutex *>(this))->Lock(); }
+ void Unlock();
+ void Unlock() const { (const_cast<CThreadFastMutex *>(this))->Unlock(); }
+
+ bool TryLock();
+ bool TryLock() const { return (const_cast<CThreadFastMutex *>(this))->TryLock(); }
+
+ //------------------------------------------------------
+ // Use this to make deadlocks easier to track by asserting
+ // when it is expected that the current thread owns the mutex
+ //------------------------------------------------------
+ bool AssertOwnedByCurrentThread();
+
+ //------------------------------------------------------
+ // Enable tracing to track deadlock problems
+ //------------------------------------------------------
+ void SetTrace( bool );
+
+private:
+ // Disallow copying
+ CThreadFastMutex( const CThreadFastMutex & );
+ //CThreadFastMutex &operator=( const CThreadFastMutex & );
+ sys_lwmutex_t m_Mutex;
+ sys_mutex_t m_SlowMutex;
+};
+
+#else
+
+typedef CThreadMutex CThreadFastMutex;
+
+#endif
+
+class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex
+{
+public:
+ CAlignedThreadFastMutex()
+ {
+ Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 );
+ }
+
+private:
+ uint8 pad[128-sizeof(CThreadFastMutex)];
+};
+
+#endif
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+class CThreadNullMutex
+{
+public:
+ static void Lock() {}
+ static void Unlock() {}
+
+ static bool TryLock() { return true; }
+ static bool AssertOwnedByCurrentThread() { return true; }
+ static void SetTrace( bool b ) {}
+
+ static uint32 GetOwnerId() { return 0; }
+ static int GetDepth() { return 0; }
+};
+
+//-----------------------------------------------------------------------------
+//
+// A mutex decorator class used to control the use of a mutex, to make it
+// less expensive when not multithreading
+//
+//-----------------------------------------------------------------------------
+
+template <class BaseClass, bool *pCondition>
+class CThreadConditionalMutex : public BaseClass
+{
+public:
+ void Lock() { if ( *pCondition ) BaseClass::Lock(); }
+ void Lock() const { if ( *pCondition ) BaseClass::Lock(); }
+ void Unlock() { if ( *pCondition ) BaseClass::Unlock(); }
+ void Unlock() const { if ( *pCondition ) BaseClass::Unlock(); }
+
+ bool TryLock() { if ( *pCondition ) return BaseClass::TryLock(); else return true; }
+ bool TryLock() const { if ( *pCondition ) return BaseClass::TryLock(); else return true; }
+ bool AssertOwnedByCurrentThread() { if ( *pCondition ) return BaseClass::AssertOwnedByCurrentThread(); else return true; }
+ void SetTrace( bool b ) { if ( *pCondition ) BaseClass::SetTrace( b ); }
+};
+
+//-----------------------------------------------------------------------------
+// Mutex decorator that blows up if another thread enters
+//-----------------------------------------------------------------------------
+
+template <class BaseClass>
+class CThreadTerminalMutex : public BaseClass
+{
+public:
+ bool TryLock() { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; }
+ bool TryLock() const { if ( !BaseClass::TryLock() ) { DebuggerBreak(); return false; } return true; }
+ void Lock() { if ( !TryLock() ) BaseClass::Lock(); }
+ void Lock() const { if ( !TryLock() ) BaseClass::Lock(); }
+
+};
+
+//-----------------------------------------------------------------------------
+//
+// Class to Lock a critical section, and unlock it automatically
+// when the lock goes out of scope
+//
+//-----------------------------------------------------------------------------
+
+template <class MUTEX_TYPE = CThreadMutex>
+class CAutoLockT
+{
+public:
+ FORCEINLINE CAutoLockT( MUTEX_TYPE &lock)
+ : m_lock(lock)
+ {
+ m_lock.Lock();
+ }
+
+ FORCEINLINE CAutoLockT(const MUTEX_TYPE &lock)
+ : m_lock(const_cast<MUTEX_TYPE &>(lock))
+ {
+ m_lock.Lock();
+ }
+
+ FORCEINLINE ~CAutoLockT()
+ {
+ m_lock.Unlock();
+ }
+
+
+private:
+ MUTEX_TYPE &m_lock;
+
+ // Disallow copying
+ CAutoLockT<MUTEX_TYPE>( const CAutoLockT<MUTEX_TYPE> & );
+ CAutoLockT<MUTEX_TYPE> &operator=( const CAutoLockT<MUTEX_TYPE> & );
+};
+
+typedef CAutoLockT<CThreadMutex> CAutoLock;
+
+//---------------------------------------------------------
+
+template <int size> struct CAutoLockTypeDeducer {};
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadMutex)> { typedef CThreadMutex Type_t; };
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadNullMutex)> { typedef CThreadNullMutex Type_t; };
+#if !defined(THREAD_PROFILER)
+template <> struct CAutoLockTypeDeducer<sizeof(CThreadFastMutex)> { typedef CThreadFastMutex Type_t; };
+template <> struct CAutoLockTypeDeducer<sizeof(CAlignedThreadFastMutex)> { typedef CAlignedThreadFastMutex Type_t; };
+#else
+template <> struct CAutoLockTypeDeducer<sizeof(CAlignedThreadFastMutex)> { typedef CAlignedThreadFastMutex Type_t; };
+#endif
+
+
+#ifdef MSVC
+#define AUTO_LOCK_( type, mutex ) \
+ CAutoLockT< typename type > UNIQUE_ID( static_cast<const type &>( mutex ) )
+#else
+// clang requires
+#define AUTO_LOCK_( type, mutex ) \
+ CAutoLockT< typename type > UNIQUE_ID( static_cast<const typename type &>( mutex ) )
+#endif
+
+#define AUTO_LOCK( mutex ) \
+ AUTO_LOCK_( CAutoLockTypeDeducer<sizeof(mutex)>::Type_t, mutex )
+
+
+#define AUTO_LOCK_FM( mutex ) \
+ AUTO_LOCK_( CAutoLockTypeDeducer<sizeof(CThreadFastMutex)>::Type_t, mutex )
+
+#define LOCAL_THREAD_LOCK_( tag ) \
+ ; \
+ static CThreadFastMutex autoMutex_##tag; \
+ AUTO_LOCK( autoMutex_##tag )
+
+#define LOCAL_THREAD_LOCK() \
+ LOCAL_THREAD_LOCK_(_)
+
+//-----------------------------------------------------------------------------
+//
+// Base class for event, semaphore and mutex objects.
+//
+//-----------------------------------------------------------------------------
+
+// TW_TIMEOUT must match WAIT_TIMEOUT definition
+#define TW_TIMEOUT 0x00000102
+// TW_FAILED must match WAIT_FAILED definition
+#define TW_FAILED 0xFFFFFFFF
+
+class PLATFORM_CLASS CThreadSyncObject
+{
+public:
+ ~CThreadSyncObject();
+
+ //-----------------------------------------------------
+ // Query if object is useful
+ //-----------------------------------------------------
+ bool operator!() const;
+
+ //-----------------------------------------------------
+ // Access handle
+ //-----------------------------------------------------
+#ifdef _WIN32
+ operator HANDLE() { return GetHandle(); }
+ const HANDLE GetHandle() const { return m_hSyncObject; }
+#endif
+ //-----------------------------------------------------
+ // Wait for a signal from the object
+ //-----------------------------------------------------
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+ //-----------------------------------------------------
+ // Wait for a signal from any of the specified objects.
+ //
+ // Returns the index of the object that signaled the event
+ // or THREADSYNC_TIMEOUT if the timeout was hit before the wait condition was met.
+ //
+ // Returns TW_FAILED if an incoming object is invalid.
+ //
+ // If bWaitAll=true, then it'll return 0 if all the objects were set.
+ //-----------------------------------------------------
+ static uint32 WaitForMultiple( int nObjects, CThreadSyncObject **ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+ // This builds a list of pointers and calls straight through to the other WaitForMultiple.
+ static uint32 WaitForMultiple( int nObjects, CThreadSyncObject *ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+protected:
+ CThreadSyncObject();
+ void AssertUseable();
+
+#ifdef _WIN32
+ HANDLE m_hSyncObject;
+ bool m_bCreatedHandle;
+#elif defined( _PS3 )
+ static sys_lwmutex_t m_staticMutex;
+ static uint32_t m_bstaticMutexInitialized;
+ static uint32_t m_bstaticMutexInitializing;
+#elif defined(POSIX)
+ pthread_mutex_t m_Mutex;
+ pthread_cond_t m_Condition;
+ bool m_bInitalized;
+ int m_cSet;
+ bool m_bManualReset;
+ bool m_bWakeForEvent;
+#else
+#error "Implement me"
+#endif
+
+private:
+ CThreadSyncObject( const CThreadSyncObject & );
+ CThreadSyncObject &operator=( const CThreadSyncObject & );
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// Wrapper for unnamed event objects
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSemaphore
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadSemaphore : public CThreadSyncObject
+{
+public:
+ CThreadSemaphore(int32 initialValue, int32 maxValue);
+
+ //-----------------------------------------------------
+ // Increases the count of the semaphore object by a specified
+ // amount. Wait() decreases the count by one on return.
+ //-----------------------------------------------------
+ bool Release(int32 releaseCount = 1, int32 * pPreviousCount = NULL );
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+private:
+ CThreadSemaphore(const CThreadSemaphore &);
+ CThreadSemaphore &operator=(const CThreadSemaphore &);
+#ifdef _PS3
+ bool AddWaitingThread();
+ void RemoveWaitingThread();
+ sys_semaphore_t m_Semaphore;
+ sys_semaphore_value_t m_sema_max_val;
+ uint32_t m_numWaitingThread;
+ uint32_t m_bInitalized;
+ uint32_t m_semaCount;
+#endif
+};
+
+#if defined( _WIN32 )
+
+//-----------------------------------------------------------------------------
+//
+// A mutex suitable for out-of-process, multi-processor usage
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadFullMutex : public CThreadSyncObject
+{
+public:
+ CThreadFullMutex( bool bEstablishInitialOwnership = false, const char * pszName = NULL );
+
+ //-----------------------------------------------------
+ // Release ownership of the mutex
+ //-----------------------------------------------------
+ bool Release();
+
+ // To match regular CThreadMutex:
+ void Lock() { Wait(); }
+ void Lock( unsigned timeout ) { Wait( timeout ); }
+ void Unlock() { Release(); }
+ bool AssertOwnedByCurrentThread() { return true; }
+ void SetTrace( bool ) {}
+
+private:
+ CThreadFullMutex( const CThreadFullMutex & );
+ CThreadFullMutex &operator=( const CThreadFullMutex & );
+};
+#endif
+
+enum NamedEventResult_t
+{
+ TT_EventDoesntExist = 0,
+ TT_EventNotSignaled,
+ TT_EventSignaled
+};
+#if defined( _PS3 )
+//---------------------------------------------------------------------------
+// CThreadEventWaitObject - the purpose of this class is to help implement
+// WaitForMultipleObejcts on PS3.
+//
+// Each event maintains a linked list of CThreadEventWaitObjects. When a
+// thread wants to wait on an event it passes the event a semaphore that
+// ptr to see the index of the event that triggered it
+//
+// The thread-specific mutex is to ensure that setting the index and setting the
+// semaphore are atomic
+//---------------------------------------------------------------------------
+
+class CThreadEventWaitObject
+{
+public:
+ CThreadEventWaitObject *m_pPrev, *m_pNext;
+ sys_semaphore_t *m_pSemaphore;
+ int m_index;
+ int *m_pFlag;
+
+ CThreadEventWaitObject() {}
+
+ void Init(sys_semaphore_t *pSem, int index, int *pFlag)
+ {
+ m_pSemaphore = pSem;
+ m_index = index;
+ m_pFlag = pFlag;
+ }
+
+ void Set();
+};
+#endif //_PS3
+
+class PLATFORM_CLASS CThreadEvent : public CThreadSyncObject
+{
+public:
+ CThreadEvent( bool fManualReset = false );
+#ifdef PLATFORM_WINDOWS
+ CThreadEvent( const char *name, bool initialState = false, bool bManualReset = false );
+ static NamedEventResult_t CheckNamedEvent( const char *name, uint32 dwTimeout = 0 );
+
+ CThreadEvent( HANDLE hHandle );
+#endif
+ //-----------------------------------------------------
+ // Set the state to signaled
+ //-----------------------------------------------------
+ bool Set();
+
+ //-----------------------------------------------------
+ // Set the state to nonsignaled
+ //-----------------------------------------------------
+ bool Reset();
+
+ //-----------------------------------------------------
+ // Check if the event is signaled
+ //-----------------------------------------------------
+ bool Check(); // Please, use for debugging only!
+
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+ // See CThreadSyncObject for definitions of these functions.
+ static uint32 WaitForMultiple( int nObjects, CThreadEvent **ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+ // To implement these, I need to check that casts are safe
+ static uint32 WaitForMultiple( int nObjects, CThreadEvent *ppObjects, bool bWaitAll, uint32 dwTimeout = TT_INFINITE );
+
+#ifdef _PS3
+ void RegisterWaitingThread(sys_semaphore_t *pSemaphore, int index, int *flag);
+ void UnregisterWaitingThread(sys_semaphore_t *pSemaphore);
+#endif
+
+protected:
+#ifdef _PS3
+ // These virtual functions need to be inline in order for the class to be exported from tier0.prx
+ virtual bool AddWaitingThread()
+ {
+ //This checks if the event is already signaled and if not creates a semaphore which will be signaled
+ //when the event is finally signaled.
+ bool result;
+
+ sys_lwmutex_lock(&m_staticMutex, 0);
+
+ if (m_bSet)
+ result=false;
+ else
+ {
+ result=true;
+
+ m_numWaitingThread++;
+
+ if ( m_numWaitingThread == 1 )
+ {
+ sys_semaphore_attribute_t semAttr;
+ sys_semaphore_attribute_initialize( semAttr );
+ int err = sys_semaphore_create( &m_Semaphore, &semAttr, 0, 256 );
+ Assert( err == CELL_OK );
+ m_bInitalized = true;
+ }
+ }
+
+ sys_lwmutex_unlock(&m_staticMutex);
+ return result;
+ }
+
+ virtual void RemoveWaitingThread()
+ {
+ sys_lwmutex_lock(&m_staticMutex, 0);
+
+ m_numWaitingThread--;
+
+ if ( m_numWaitingThread == 0)
+ {
+ int err = sys_semaphore_destroy( m_Semaphore );
+ Assert( err == CELL_OK );
+ m_bInitalized = false;
+ }
+
+ sys_lwmutex_unlock(&m_staticMutex);
+ }
+#endif
+private:
+ CThreadEvent( const CThreadEvent & );
+ CThreadEvent &operator=( const CThreadEvent & );
+#if defined( _PS3 )
+ uint32_t m_bSet;
+ bool m_bManualReset;
+
+ sys_semaphore_t m_Semaphore;
+ uint32_t m_numWaitingThread;
+ uint32_t m_bInitalized;
+
+ CThreadEventWaitObject m_waitObjects[CTHREADEVENT_MAX_WAITING_THREADS+2];
+ CThreadEventWaitObject *m_pWaitObjectsPool;
+ CThreadEventWaitObject *m_pWaitObjectsList;
+
+ CThreadEventWaitObject* LLUnlinkNode(CThreadEventWaitObject *node);
+ CThreadEventWaitObject* LLLinkNode(CThreadEventWaitObject* list, CThreadEventWaitObject *node);
+
+#endif
+};
+
+// Hard-wired manual event for use in array declarations
+class CThreadManualEvent : public CThreadEvent
+{
+public:
+ CThreadManualEvent()
+ : CThreadEvent( true )
+ {
+ }
+};
+
+PLATFORM_INTERFACE int ThreadWaitForObjects( int nEvents, const HANDLE *pHandles, bool bWaitAll = true, unsigned timeout = TT_INFINITE );
+inline int ThreadWaitForEvents( int nEvents, const CThreadEvent *pEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) { return ThreadWaitForObjects( nEvents, (const HANDLE *)pEvents, bWaitAll, timeout ); }
+
+//-----------------------------------------------------------------------------
+//
+// CThreadRWLock
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadRWLock
+{
+public:
+ CThreadRWLock();
+
+ void LockForRead();
+ void UnlockRead();
+ void LockForWrite();
+ void UnlockWrite();
+
+ void LockForRead() const { const_cast<CThreadRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadRWLock *>(this)->UnlockWrite(); }
+
+private:
+ void WaitForRead();
+
+#ifdef WIN32
+ CThreadFastMutex m_mutex;
+#else
+ CThreadMutex m_mutex;
+#endif
+ CThreadEvent m_CanWrite;
+ CThreadEvent m_CanRead;
+
+ int m_nWriters;
+ int m_nActiveReaders;
+ int m_nPendingReaders;
+};
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSpinRWLock
+//
+//-----------------------------------------------------------------------------
+
+#ifndef OLD_SPINRWLOCK
+class ALIGN8 PLATFORM_CLASS CThreadSpinRWLock
+{
+public:
+ CThreadSpinRWLock()
+ {
+ m_lockInfo.m_i32 = 0;
+ m_writerId = 0;
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ m_iWriteDepth = 0;
+#endif
+ }
+
+ bool IsLockedForWrite();
+ bool IsLockedForRead();
+
+ FORCEINLINE bool TryLockForWrite();
+ bool TryLockForWrite_UnforcedInline();
+
+ void LockForWrite();
+ void SpinLockForWrite();
+
+ FORCEINLINE bool TryLockForRead();
+ bool TryLockForRead_UnforcedInline();
+
+ void LockForRead();
+ void SpinLockForRead();
+
+ void UnlockWrite();
+ void UnlockRead();
+
+ bool TryLockForWrite() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForWrite(); }
+ bool TryLockForRead() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForRead(); }
+ void LockForRead() const { const_cast<CThreadSpinRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadSpinRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadSpinRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadSpinRWLock *>(this)->UnlockWrite(); }
+
+private:
+ enum
+ {
+ THREAD_SPIN = (8*1024)
+ };
+
+ union LockInfo_t
+ {
+ struct
+ {
+#if PLAT_LITTLE_ENDIAN
+ uint16 m_nReaders;
+ uint16 m_fWriting;
+#else
+ uint16 m_fWriting;
+ uint16 m_nReaders;
+#endif
+ };
+ uint32 m_i32;
+ };
+
+ LockInfo_t m_lockInfo;
+ uint32 m_writerId;
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ int m_iWriteDepth;
+ uint32 pad;
+#endif
+} ALIGN8_POST;
+
+#else
+
+/* (commented out to reduce distraction in colorized editor, remove entirely when new implementation settles)
+class ALIGN8 PLATFORM_CLASS CThreadSpinRWLock
+{
+public:
+ CThreadSpinRWLock() { COMPILE_TIME_ASSERT( sizeof( LockInfo_t ) == sizeof( int64 ) ); Assert( (intp)this % 8 == 0 ); memset( this, 0, sizeof( *this ) ); }
+
+ bool TryLockForWrite();
+ bool TryLockForRead();
+
+ void LockForRead();
+ void UnlockRead();
+ void LockForWrite();
+ void UnlockWrite();
+
+ bool TryLockForWrite() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForWrite(); }
+ bool TryLockForRead() const { return const_cast<CThreadSpinRWLock *>(this)->TryLockForRead(); }
+ void LockForRead() const { const_cast<CThreadSpinRWLock *>(this)->LockForRead(); }
+ void UnlockRead() const { const_cast<CThreadSpinRWLock *>(this)->UnlockRead(); }
+ void LockForWrite() const { const_cast<CThreadSpinRWLock *>(this)->LockForWrite(); }
+ void UnlockWrite() const { const_cast<CThreadSpinRWLock *>(this)->UnlockWrite(); }
+
+private:
+ // This structure is used as an atomic & exchangeable 64-bit value. It would probably be better to just have one 64-bit value
+ // and accessor functions that make/break it, but at this late stage of development, I'm just wrapping it into union
+ // Beware of endianness: on Xbox/PowerPC m_writerId is high-word of m_i64; on PC, it's low-dword of m_i64
+ union LockInfo_t
+ {
+ struct
+ {
+ uint32 m_writerId;
+ int m_nReaders;
+ };
+ int64 m_i64;
+ };
+
+ bool AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand );
+ bool TryLockForWrite( const uint32 threadId );
+ void SpinLockForWrite( const uint32 threadId );
+
+ volatile LockInfo_t m_lockInfo;
+ CInterlockedInt m_nWriters;
+} ALIGN8_POST;
+*/
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// A thread wrapper similar to a Java thread.
+//
+//-----------------------------------------------------------------------------
+#ifdef _PS3
+// Everything must be inline for this to work across PRX boundaries
+
+class CThread;
+PLATFORM_INTERFACE CThread *GetCurThreadPS3();
+PLATFORM_INTERFACE void SetCurThreadPS3( CThread * );
+PLATFORM_INTERFACE void AllocateThreadID( void );
+PLATFORM_INTERFACE void FreeThreadID( void );
+#endif
+
+class PLATFORM_CLASS CThread
+{
+public:
+ CThread();
+ virtual ~CThread();
+
+ //-----------------------------------------------------
+
+ const char *GetName();
+ void SetName( const char *pszName );
+
+ size_t CalcStackDepth( void *pStackVariable ) { return ((byte *)m_pStackBase - (byte *)pStackVariable); }
+
+ //-----------------------------------------------------
+ // Functions for the other threads
+ //-----------------------------------------------------
+
+ // Start thread running - error if already running
+ enum ThreadPriorityEnum_t
+ {
+#ifdef _PS3
+ PRIORITY_NORMAL = 1001,
+ PRIORITY_HIGH = 100,
+ PRIORITY_LOW = 2001,
+ PRIORITY_DEFAULT = 1001
+#else
+ PRIORITY_DEFAULT = 0,//THREAD_PRIORITY_NORMAL,
+ PRIORITY_NORMAL = 0,//THREAD_PRIORITY_NORMAL,
+ PRIORITY_HIGH = 1,//THREAD_PRIORITY_ABOVE_NORMAL,
+ PRIORITY_LOW = -1//THREAD_PRIORITY_BELOW_NORMAL
+#endif
+ };
+ virtual bool Start( unsigned nBytesStack = 0, ThreadPriorityEnum_t nPriority = PRIORITY_DEFAULT );
+
+ // Returns true if thread has been created and hasn't yet exited
+ bool IsAlive();
+
+ // This method causes the current thread to wait until this thread
+ // is no longer alive.
+ bool Join( unsigned timeout = TT_INFINITE );
+
+ // Access the thread handle directly
+ ThreadHandle_t GetThreadHandle();
+
+#ifdef _WIN32
+ uint GetThreadId();
+#endif
+
+ //-----------------------------------------------------
+
+ int GetResult();
+
+ //-----------------------------------------------------
+ // Functions for both this, and maybe, and other threads
+ //-----------------------------------------------------
+
+ // Forcibly, abnormally, but relatively cleanly stop the thread
+ void Stop( int exitCode = 0 );
+
+ // Get the priority
+ int GetPriority() const;
+
+ // Set the priority
+ bool SetPriority( int priority );
+
+ // Suspend a thread, can only call from the thread itself
+ unsigned Suspend();
+
+ // Resume a suspended thread
+ unsigned Resume();
+
+ // Check if thread is suspended
+ bool IsSuspended() { return !m_NotSuspendedEvent.Check(); }
+
+ // Force hard-termination of thread. Used for critical failures.
+ bool Terminate( int exitCode = 0 );
+
+ //-----------------------------------------------------
+ // Global methods
+ //-----------------------------------------------------
+
+ // Get the Thread object that represents the current thread, if any.
+ // Can return NULL if the current thread was not created using
+ // CThread
+ static CThread *GetCurrentCThread();
+
+ // Offer a context switch. Under Win32, equivalent to Sleep(0)
+#ifdef Yield
+#undef Yield
+#endif
+ static void Yield();
+
+ // This method causes the current thread to yield and not to be
+ // scheduled for further execution until a certain amount of real
+ // time has elapsed, more or less. Duration is in milliseconds
+ static void Sleep( unsigned duration );
+
+protected:
+
+ // Optional pre-run call, with ability to fail-create. Note Init()
+ // is forced synchronous with Start()
+ virtual bool Init();
+
+ // Thread will run this function on startup, must be supplied by
+ // derived class, performs the intended action of the thread.
+ virtual int Run() = 0;
+
+ // Called when the thread exits
+ virtual void OnExit();
+
+ // Allow for custom start waiting
+ virtual bool WaitForCreateComplete( CThreadEvent *pEvent );
+ const ThreadId_t GetThreadID() const { return (ThreadId_t)m_threadId; }
+
+#ifdef PLATFORM_WINDOWS
+ const ThreadHandle_t GetThreadHandle() const { return (ThreadHandle_t)m_hThread; }
+
+ static unsigned long __stdcall ThreadProc( void * pv );
+ typedef unsigned long (__stdcall *ThreadProc_t)( void * );
+#else
+ static void* ThreadProc( void * pv );
+ typedef void* (*ThreadProc_t)( void * pv );
+#endif
+
+ virtual ThreadProc_t GetThreadProc();
+ CThreadMutex m_Lock;
+ CThreadEvent m_ExitEvent; // Set right before the thread's function exits.
+
+private:
+ enum Flags
+ {
+ SUPPORT_STOP_PROTOCOL = 1 << 0
+ };
+
+ // Thread initially runs this. param is actually 'this'. function
+ // just gets this and calls ThreadProc
+ struct ThreadInit_t
+ {
+ CThread * pThread;
+ CThreadEvent *pInitCompleteEvent;
+ bool * pfInitSuccess;
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ void * ParentStackTrace[THREAD_PARENT_STACK_TRACE_LENGTH];
+#endif
+ };
+
+ // make copy constructor and assignment operator inaccessible
+ CThread( const CThread & );
+ CThread &operator=( const CThread & );
+
+#ifdef _WIN32
+ HANDLE m_hThread;
+ ThreadId_t m_threadId;
+#elif defined( _PS3 )
+ sys_ppu_thread_t m_threadId;
+ volatile sys_ppu_thread_t m_threadZombieId;
+
+ // Mutex and condition variable used by the Suspend / Resume logic
+ sys_mutex_t m_mutexSuspend;
+ sys_cond_t m_condSuspend;
+
+ //EAPS3 Event to indicate that a thread has terminated. This helps with the replacing of WaitForMultipleObjects
+ // on the PS3, since it waits for a thread to finish.
+ CThreadEvent m_threadEnd;
+#elif defined(_POSIX)
+ pthread_t m_threadId;
+ volatile pthread_t m_threadZombieId;
+#endif
+ int m_result;
+ char m_szName[32];
+ void * m_pStackBase;
+ unsigned m_flags;
+ CThreadManualEvent m_NotSuspendedEvent;
+};
+
+// The CThread implementation needs to be inlined for performance on the PS3 - It makes a difference of more than 1ms/frame
+// Since the dependency checker isn't smart enough to take an #ifdef _PS3 into account, all platforms will inline it.
+#ifdef _PS3
+#include "threadtools.inl"
+#endif
+
+//-----------------------------------------------------------------------------
+// Simple thread class encompasses the notion of a worker thread, handing
+// synchronized communication.
+//-----------------------------------------------------------------------------
+
+// These are internal reserved error results from a call attempt
+enum WTCallResult_t
+{
+ WTCR_FAIL = -1,
+ WTCR_TIMEOUT = -2,
+ WTCR_THREAD_GONE = -3,
+};
+
+class PLATFORM_CLASS CWorkerThread : public CThread
+{
+public:
+ CWorkerThread();
+
+ //-----------------------------------------------------
+ //
+ // Inter-thread communication
+ //
+ // Calls in either direction take place on the same "channel."
+ // Seperate functions are specified to make identities obvious
+ //
+ //-----------------------------------------------------
+
+ // Master: Signal the thread, and block for a response
+ int CallWorker( unsigned, unsigned timeout = TT_INFINITE, bool fBoostWorkerPriorityToMaster = true );
+
+ // Worker: Signal the thread, and block for a response
+ int CallMaster( unsigned, unsigned timeout = TT_INFINITE );
+
+ // Wait for the next request
+ bool WaitForCall( unsigned dwTimeout, unsigned *pResult = NULL );
+ bool WaitForCall( unsigned *pResult = NULL );
+
+ // Is there a request?
+ bool PeekCall( unsigned *pParam = NULL );
+
+ // Reply to the request
+ void Reply( unsigned );
+
+ // Wait for a reply in the case when CallWorker() with timeout != TT_INFINITE
+ int WaitForReply( unsigned timeout = TT_INFINITE );
+
+ // If you want to do WaitForMultipleObjects you'll need to include
+ // this handle in your wait list or you won't be responsive
+ CThreadEvent& GetCallHandle(); // (returns m_EventSend)
+
+ // Find out what the request was
+ unsigned GetCallParam() const;
+
+ // Boost the worker thread to the master thread, if worker thread is lesser, return old priority
+ int BoostPriority();
+
+protected:
+ typedef uint32 ( *WaitFunc_t)( uint32 nHandles, CThreadEvent** ppHandles, int bWaitAll, uint32 timeout );
+ int Call( unsigned, unsigned timeout, bool fBoost, WaitFunc_t = NULL );
+ int WaitForReply( unsigned timeout, WaitFunc_t );
+
+private:
+ CWorkerThread( const CWorkerThread & );
+ CWorkerThread &operator=( const CWorkerThread & );
+
+ CThreadEvent m_EventSend;
+ CThreadEvent m_EventComplete;
+
+ unsigned m_Param;
+ int m_ReturnVal;
+};
+
+
+// a unidirectional message queue. A queue of type T. Not especially high speed since each message
+// is malloced/freed. Note that if your message class has destructors/constructors, they MUST be
+// thread safe!
+template<class T> class CMessageQueue
+{
+ CThreadEvent SignalEvent; // signals presence of data
+ CThreadMutex QueueAccessMutex;
+
+ // the parts protected by the mutex
+ struct MsgNode
+ {
+ MsgNode *Next;
+ T Data;
+ };
+
+ MsgNode *Head;
+ MsgNode *Tail;
+
+public:
+ CMessageQueue( void )
+ {
+ Head = Tail = NULL;
+ }
+
+ // check for a message. not 100% reliable - someone could grab the message first
+ bool MessageWaiting( void )
+ {
+ return ( Head != NULL );
+ }
+
+ void WaitMessage( T *pMsg )
+ {
+ for(;;)
+ {
+ while( ! MessageWaiting() )
+ SignalEvent.Wait();
+ QueueAccessMutex.Lock();
+ if (! Head )
+ {
+ // multiple readers could make this null
+ QueueAccessMutex.Unlock();
+ continue;
+ }
+ *( pMsg ) = Head->Data;
+ MsgNode *remove_this = Head;
+ Head = Head->Next;
+ if (! Head) // if empty, fix tail ptr
+ Tail = NULL;
+ QueueAccessMutex.Unlock();
+ delete remove_this;
+ break;
+ }
+ }
+
+ void QueueMessage( T const &Msg)
+ {
+ MsgNode *new1=new MsgNode;
+ new1->Data=Msg;
+ new1->Next=NULL;
+ QueueAccessMutex.Lock();
+ if ( Tail )
+ {
+ Tail->Next=new1;
+ Tail = new1;
+ }
+ else
+ {
+ Head = new1;
+ Tail = new1;
+ }
+ SignalEvent.Set();
+ QueueAccessMutex.Unlock();
+ }
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadMutex. Inlining to reduce overhead and to allow client code
+// to decide debug status (tracing)
+//
+//-----------------------------------------------------------------------------
+
+#ifdef MSVC
+typedef struct _RTL_CRITICAL_SECTION RTL_CRITICAL_SECTION;
+typedef RTL_CRITICAL_SECTION CRITICAL_SECTION;
+
+#ifndef _X360
+extern "C"
+{
+ void __declspec(dllimport) __stdcall InitializeCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall EnterCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall LeaveCriticalSection(CRITICAL_SECTION *);
+ void __declspec(dllimport) __stdcall DeleteCriticalSection(CRITICAL_SECTION *);
+};
+#endif
+#endif
+
+//---------------------------------------------------------
+#if !defined(POSIX) || defined( _GAMECONSOLE )
+
+inline void CThreadMutex::Lock()
+{
+#if defined(_PS3)
+ #ifndef NO_THREAD_SYNC
+ sys_mutex_lock( m_Mutex, 0 );
+ #endif
+#else
+ #if defined( THREAD_MUTEX_TRACING_ENABLED )
+ uint thisThreadID = ThreadGetCurrentId();
+ if ( m_bTrace && m_currentOwnerID && ( m_currentOwnerID != thisThreadID ) )
+ Msg( _T( "Thread %u about to wait for lock %x owned by %u\n" ), ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ #endif
+
+ LockSilent();
+
+ #ifdef THREAD_MUTEX_TRACING_ENABLED
+ if (m_lockCount == 0)
+ {
+ // we now own it for the first time. Set owner information
+ m_currentOwnerID = thisThreadID;
+ if ( m_bTrace )
+ Msg( _T( "Thread %u now owns lock 0x%x\n" ), m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ }
+ m_lockCount++;
+ #endif
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Unlock()
+{
+#if defined( _PS3 )
+
+ #ifndef NO_THREAD_SYNC
+ sys_mutex_unlock( m_Mutex );
+ #endif
+
+#else
+ #ifdef THREAD_MUTEX_TRACING_ENABLED
+ AssertMsg( m_lockCount >= 1, "Invalid unlock of thread lock" );
+ m_lockCount--;
+ if (m_lockCount == 0)
+ {
+ if ( m_bTrace )
+ Msg( _T( "Thread %u releasing lock 0x%x\n" ), m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ m_currentOwnerID = 0;
+ }
+ #endif
+ UnlockSilent();
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::LockSilent()
+{
+ #ifdef MSVC
+ EnterCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+ #else
+ DebuggerBreak(); // should not be called - not defined for this platform/compiler!!!
+ #endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::UnlockSilent()
+{
+ #ifdef MSVC
+ LeaveCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+ #else
+ DebuggerBreak(); // should not be called - not defined for this platform/compiler!!!
+ #endif
+}
+
+//---------------------------------------------------------
+
+inline bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+#ifdef _WIN32
+ if (ThreadGetCurrentId() == m_currentOwnerID)
+ return true;
+ AssertMsg3( 0, "Expected thread %u as owner of lock 0x%x, but %u owns", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ return false;
+#elif defined( _PS3 )
+ return true;
+#endif
+#else
+ return true;
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace( bool bTrace )
+{
+#ifdef _WIN32
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+ m_bTrace = bTrace;
+#endif
+#elif defined _PS3
+ //EAPS3
+#endif
+
+}
+
+//---------------------------------------------------------
+
+#elif defined(POSIX) && !defined( _GAMECONSOLE )
+
+inline CThreadMutex::CThreadMutex()
+{
+ // enable recursive locks as we need them
+ pthread_mutexattr_init( &m_Attr );
+ pthread_mutexattr_settype( &m_Attr, PTHREAD_MUTEX_RECURSIVE );
+ pthread_mutex_init( &m_Mutex, &m_Attr );
+}
+
+//---------------------------------------------------------
+
+inline CThreadMutex::~CThreadMutex()
+{
+ pthread_mutex_destroy( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Lock()
+{
+ pthread_mutex_lock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Unlock()
+{
+ pthread_mutex_unlock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::LockSilent()
+{
+ pthread_mutex_lock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::UnlockSilent()
+{
+ pthread_mutex_unlock( &m_Mutex );
+}
+
+//---------------------------------------------------------
+
+inline bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+ return true;
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace(bool fTrace)
+{
+}
+
+#else
+#error
+#endif // POSIX
+
+//-----------------------------------------------------------------------------
+//
+// CThreadRWLock inline functions
+//
+//-----------------------------------------------------------------------------
+
+inline CThreadRWLock::CThreadRWLock()
+: m_CanRead( true ),
+ m_nWriters( 0 ),
+ m_nActiveReaders( 0 ),
+ m_nPendingReaders( 0 )
+{
+}
+
+inline void CThreadRWLock::LockForRead()
+{
+ m_mutex.Lock();
+ if ( m_nWriters)
+ {
+ WaitForRead();
+ }
+ m_nActiveReaders++;
+ m_mutex.Unlock();
+}
+
+inline void CThreadRWLock::UnlockRead()
+{
+ m_mutex.Lock();
+ m_nActiveReaders--;
+ if ( m_nActiveReaders == 0 && m_nWriters != 0 )
+ {
+ m_CanWrite.Set();
+ }
+ m_mutex.Unlock();
+}
+
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSpinRWLock inline functions
+//
+//-----------------------------------------------------------------------------
+
+#ifndef OLD_SPINRWLOCK
+
+#if defined(TEST_THREAD_SPIN_RW_LOCK)
+#define RWLAssert( exp ) if ( exp ) ; else DebuggerBreak();
+#else
+#define RWLAssert( exp ) ((void)0)
+#endif
+
+inline bool CThreadSpinRWLock::IsLockedForWrite()
+{
+ return ( m_lockInfo.m_fWriting == 1 );
+}
+
+inline bool CThreadSpinRWLock::IsLockedForRead()
+{
+ return ( m_lockInfo.m_nReaders > 0 );
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForWrite()
+{
+ volatile LockInfo_t &curValue = m_lockInfo;
+ if ( !( curValue.m_i32 & 0x00010000 ) && ThreadInterlockedAssignIf( &curValue.m_i32, 0x00010000, 0 ) )
+ {
+ ThreadMemoryBarrier();
+ RWLAssert( m_iWriteDepth == 0 && m_writerId == 0 );
+ m_writerId = ThreadGetCurrentId();
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ m_iWriteDepth++;
+#endif
+ return true;
+ }
+
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForWrite_UnforcedInline()
+{
+ if ( TryLockForWrite() )
+ {
+ return true;
+ }
+
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( m_writerId != ThreadGetCurrentId() )
+ {
+ return false;
+ }
+ m_iWriteDepth++;
+ return true;
+#else
+ return false;
+#endif
+}
+
+FORCEINLINE void CThreadSpinRWLock::LockForWrite()
+{
+ if ( !TryLockForWrite() )
+ {
+ SpinLockForWrite();
+ }
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForRead()
+{
+ volatile LockInfo_t &curValue = m_lockInfo;
+ if ( !( curValue.m_i32 & 0x00010000 ) ) // !m_lockInfo.m_fWriting
+ {
+ LockInfo_t oldValue;
+ LockInfo_t newValue;
+ oldValue.m_i32 = ( curValue.m_i32 & 0xffff );
+ newValue.m_i32 = oldValue.m_i32 + 1;
+
+ if ( ThreadInterlockedAssignIf( &m_lockInfo.m_i32, newValue.m_i32, oldValue.m_i32 ) )
+ {
+ ThreadMemoryBarrier();
+ RWLAssert( m_lockInfo.m_fWriting == 0 );
+ return true;
+ }
+ }
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForRead_UnforcedInline()
+{
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( m_lockInfo.m_i32 & 0x00010000 ) // m_lockInfo.m_fWriting
+ {
+ if ( m_writerId == ThreadGetCurrentId() )
+ {
+ m_lockInfo.m_nReaders++;
+ return true;
+ }
+
+ return false;
+ }
+#endif
+ return TryLockForRead();
+}
+
+FORCEINLINE void CThreadSpinRWLock::LockForRead()
+{
+ if ( !TryLockForRead() )
+ {
+ SpinLockForRead();
+ }
+}
+
+FORCEINLINE void CThreadSpinRWLock::UnlockWrite()
+{
+ RWLAssert( m_writerId == ThreadGetCurrentId() );
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( --m_iWriteDepth == 0 )
+#endif
+ {
+ m_writerId = 0;
+ ThreadMemoryBarrier();
+ m_lockInfo.m_i32 = 0;
+ }
+}
+
+#ifndef REENTRANT_THREAD_SPIN_RW_LOCK
+FORCEINLINE
+#else
+inline
+#endif
+void CThreadSpinRWLock::UnlockRead()
+{
+ RWLAssert( m_writerId == 0 || ( m_writerId == ThreadGetCurrentId() && m_lockInfo.m_fWriting ) );
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ if ( !( m_lockInfo.m_i32 & 0x00010000 ) ) // !m_lockInfo.m_fWriting
+#endif
+ {
+ ThreadMemoryBarrier();
+ ThreadInterlockedDecrement( &m_lockInfo.m_i32 );
+ RWLAssert( m_writerId == 0 && !m_lockInfo.m_fWriting );
+ }
+#ifdef REENTRANT_THREAD_SPIN_RW_LOCK
+ else if ( m_writerId == ThreadGetCurrentId() )
+ {
+ m_lockInfo.m_nReaders--;
+ }
+ else
+ {
+ RWLAssert( 0 );
+ }
+#endif
+}
+
+#else
+/* (commented out to reduce distraction in colorized editor, remove entirely when new implementation settles)
+inline bool CThreadSpinRWLock::AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand )
+{
+ // Note: using unions guarantees no aliasing bugs. Casting structures through *(int64*)&
+ // may create hard-to-catch bugs because when you do that, compiler doesn't know that the newly computed pointer
+ // is actually aliased with LockInfo_t structure. It's rarely a problem in practice, but when it is, it's a royal pain to debug.
+ return ThreadInterlockedAssignIf64( &m_lockInfo.m_i64, newValue.m_i64, comperand.m_i64 );
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForWrite( const uint32 threadId )
+{
+ // In order to grab a write lock, there can be no readers and no owners of the write lock
+ if ( m_lockInfo.m_nReaders > 0 || ( m_lockInfo.m_writerId && m_lockInfo.m_writerId != threadId ) )
+ {
+ return false;
+ }
+
+ static const LockInfo_t oldValue = { {0, 0} };
+ LockInfo_t newValue = { { threadId, 0 } };
+ if ( AssignIf( newValue, oldValue ) )
+ {
+ ThreadMemoryBarrier();
+ return true;
+ }
+ return false;
+}
+
+inline bool CThreadSpinRWLock::TryLockForWrite()
+{
+ m_nWriters++;
+ if ( !TryLockForWrite( ThreadGetCurrentId() ) )
+ {
+ m_nWriters--;
+ return false;
+ }
+ return true;
+}
+
+FORCEINLINE bool CThreadSpinRWLock::TryLockForRead()
+{
+ if ( m_nWriters != 0 )
+ {
+ return false;
+ }
+ // In order to grab a write lock, the number of readers must not change and no thread can own the write
+ LockInfo_t oldValue;
+ LockInfo_t newValue;
+
+ if( IsX360() || IsPS3() )
+ {
+ // this is the code equivalent to original code (see below) that doesn't cause LHS on Xbox360
+ // WARNING: This code assumes BIG Endian CPU
+ oldValue.m_i64 = uint32( m_lockInfo.m_nReaders );
+ newValue.m_i64 = oldValue.m_i64 + 1; // NOTE: when we have -1 (or 0xFFFFFFFF) readers, this will result in non-equivalent code
+ }
+ else
+ {
+ // this is the original code that worked here for a while
+ oldValue.m_nReaders = m_lockInfo.m_nReaders;
+ oldValue.m_writerId = 0;
+ newValue.m_nReaders = oldValue.m_nReaders + 1;
+ newValue.m_writerId = 0;
+ }
+
+ if ( AssignIf( newValue, oldValue ) )
+ {
+ ThreadMemoryBarrier();
+ return true;
+ }
+ return false;
+}
+
+inline void CThreadSpinRWLock::LockForWrite()
+{
+ const uint32 threadId = ThreadGetCurrentId();
+
+ m_nWriters++;
+
+ if ( !TryLockForWrite( threadId ) )
+ {
+ ThreadPause();
+ SpinLockForWrite( threadId );
+ }
+}
+*/
+#endif
+
+// read data from a memory address
+template<class T> FORCEINLINE T ReadVolatileMemory( T const *pPtr )
+{
+ volatile const T * pVolatilePtr = ( volatile const T * ) pPtr;
+ return *pVolatilePtr;
+}
+
+
+//-----------------------------------------------------------------------------
+
+#if defined( _WIN32 )
+#pragma warning(pop)
+#endif
+
+#if defined( _PS3 )
+BOOL SetEvent( CThreadEvent *pEvent );
+BOOL ResetEvent( CThreadEvent *pEvent );
+DWORD WaitForMultipleObjects(DWORD nCount, CThreadEvent **lppHandles, BOOL bWaitAll, DWORD dwMilliseconds );
+#endif // _PS3
+#endif // THREADTOOLS_H
diff --git a/external/vpc/public/tier0/threadtools.inl b/external/vpc/public/tier0/threadtools.inl
new file mode 100644
index 0000000..0afe97a
--- /dev/null
+++ b/external/vpc/public/tier0/threadtools.inl
@@ -0,0 +1,629 @@
+#ifndef THREADTOOLS_INL
+#define THREADTOOLS_INL
+
+// This file is included in threadtools.h for PS3 and threadtools.cpp for all other platforms
+//
+// Do not #include other files here
+
+#ifndef _PS3
+// this is defined in the .cpp for the PS3 to avoid introducing a dependency for files including the header
+CTHREADLOCALPTR(CThread) g_pCurThread;
+
+#define INLINE_ON_PS3
+#else
+// Inlining these functions on PS3 (which are called across PRX boundaries) saves us over 1ms per frame
+#define INLINE_ON_PS3 inline
+#endif
+
+INLINE_ON_PS3 CThread::CThread() :
+#ifdef _WIN32
+m_hThread( NULL ),
+m_threadId( 0 ),
+#elif defined( _PS3 ) || defined(_POSIX)
+m_threadId( 0 ),
+m_threadZombieId( 0 ) ,
+#endif
+m_result( 0 ),
+m_flags( 0 )
+{
+ m_szName[0] = 0;
+ m_NotSuspendedEvent.Set();
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 CThread::~CThread()
+{
+#ifdef MSVC
+ if (m_hThread)
+#elif defined(POSIX) && !defined( _PS3 )
+ if ( m_threadId )
+#endif
+ {
+ if ( IsAlive() )
+ {
+ Msg( "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
+#ifdef _WIN32
+
+ DoNewAssertDialog( __FILE__, __LINE__, "Illegal termination of worker thread! Threads must negotiate an end to the thread before the CThread object is destroyed.\n" );
+#endif
+ if ( GetCurrentCThread() == this )
+ {
+ Stop(); // BUGBUG: Alfred - this doesn't make sense, this destructor fires from the hosting thread not the thread itself!!
+ }
+ }
+ }
+#if defined(POSIX) || defined( _PS3 )
+ if ( m_threadZombieId )
+ {
+ // just clean up zombie threads immediately (the destructor is fired from the hosting thread)
+ Join();
+ }
+#endif
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 const char *CThread::GetName()
+{
+ AUTO_LOCK( m_Lock );
+ if ( !m_szName[0] )
+ {
+#if defined( _WIN32 )
+ _snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/%p)", this, m_hThread );
+#elif defined( _PS3 )
+ snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p)", this );
+#elif defined( POSIX )
+ _snprintf( m_szName, sizeof(m_szName) - 1, "Thread(%p/0x%x)", this, (uint)m_threadId );
+#endif
+ m_szName[sizeof(m_szName) - 1] = 0;
+ }
+ return m_szName;
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 void CThread::SetName(const char *pszName)
+{
+ AUTO_LOCK( m_Lock );
+ strncpy( m_szName, pszName, sizeof(m_szName) - 1 );
+ m_szName[sizeof(m_szName) - 1] = 0;
+}
+
+//-----------------------------------------------------
+// Functions for the other threads
+//-----------------------------------------------------
+
+// Start thread running - error if already running
+INLINE_ON_PS3 bool CThread::Start( unsigned nBytesStack, ThreadPriorityEnum_t nPriority )
+{
+ AUTO_LOCK( m_Lock );
+
+ if ( IsAlive() )
+ {
+ AssertMsg( 0, "Tried to create a thread that has already been created!" );
+ return false;
+ }
+
+ bool bInitSuccess = false;
+ CThreadEvent createComplete;
+ ThreadInit_t init = { this, &createComplete, &bInitSuccess };
+
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ {
+ int iValidEntries = GetCallStack_Fast( init.ParentStackTrace, ARRAYSIZE( init.ParentStackTrace ), 0 );
+ for( int i = iValidEntries; i < ARRAYSIZE( init.ParentStackTrace ); ++i )
+ {
+ init.ParentStackTrace[i] = NULL;
+ }
+ }
+#endif
+
+#ifdef PLATFORM_WINDOWS
+ m_hThread = (HANDLE)CreateThread( NULL,
+ nBytesStack,
+ (LPTHREAD_START_ROUTINE)GetThreadProc(),
+ new ThreadInit_t(init),
+ 0,
+ (LPDWORD)&m_threadId );
+
+ if( nPriority != PRIORITY_DEFAULT )
+ {
+ SetThreadPriority( m_hThread, nPriority );
+ }
+
+ if ( !m_hThread )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
+ return false;
+ }
+#elif PLATFORM_PS3
+ // On the PS3, a stack size of 0 doesn't imply a default stack size, so we need to force it to our
+ // own default size.
+ if ( nBytesStack == 0 )
+ {
+ nBytesStack = PS3_SYS_PPU_THREAD_COMMON_STACK_SIZE;
+ }
+
+ //The thread is about to begin
+ m_threadEnd.Reset();
+
+ // sony documentation:
+ // "If the PPU thread is not joined by sys_ppu_thread_join() after exit,
+ // it should always be created as non-joinable (not specifying
+ // SYS_PPU_THREAD_CREATE_JOINABLE). Otherwise, some resources are left
+ // allocated after termination of the PPU thread as if memory leaks."
+ const char* threadName=m_szName;
+ if ( sys_ppu_thread_create( &m_threadId,
+ (void(*)(uint64_t))GetThreadProc(),
+ (uint64_t)(new ThreadInit_t( init )),
+ nPriority,
+ nBytesStack,
+ SYS_PPU_THREAD_CREATE_JOINABLE ,
+ threadName ) != CELL_OK )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", errno );
+ return false;
+ }
+
+ bInitSuccess = true;
+#elif PLATFORM_POSIX
+ pthread_attr_t attr;
+ pthread_attr_init( &attr );
+ pthread_attr_setstacksize( &attr, MAX( nBytesStack, 1024u*1024 ) );
+ if ( pthread_create( &m_threadId, &attr, (void *(*)(void *))GetThreadProc(), new ThreadInit_t( init ) ) != 0 )
+ {
+ AssertMsg1( 0, "Failed to create thread (error 0x%x)", GetLastError() );
+ return false;
+ }
+ bInitSuccess = true;
+#endif
+
+
+
+ if ( !WaitForCreateComplete( &createComplete ) )
+ {
+ Msg( "Thread failed to initialize\n" );
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ m_hThread = NULL;
+#elif defined( _PS3 )
+ m_threadEnd.Set();
+ m_threadId = NULL;
+ m_threadZombieId = 0;
+#endif
+
+ return false;
+ }
+
+ if ( !bInitSuccess )
+ {
+ Msg( "Thread failed to initialize\n" );
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ m_hThread = NULL;
+#elif defined(POSIX) && !defined( _PS3 )
+ m_threadId = 0;
+ m_threadZombieId = 0;
+#endif
+ return false;
+ }
+
+#ifdef _WIN32
+ if ( !m_hThread )
+ {
+ Msg( "Thread exited immediately\n" );
+ }
+#endif
+
+#ifdef _WIN32
+ AddThreadHandleToIDMap( m_hThread, m_threadId );
+ return !!m_hThread;
+#elif defined(POSIX)
+ return !!m_threadId;
+#endif
+}
+
+//---------------------------------------------------------
+//
+// Return true if the thread has been created and hasn't yet exited
+//
+
+INLINE_ON_PS3 bool CThread::IsAlive()
+{
+#ifdef PLATFORM_WINDOWS
+ DWORD dwExitCode;
+ return (
+ m_hThread
+ && GetExitCodeThread(m_hThread, &dwExitCode)
+ && dwExitCode == STILL_ACTIVE );
+#elif defined(POSIX)
+ return !!m_threadId;
+#endif
+}
+
+// This method causes the current thread to wait until this thread
+// is no longer alive.
+INLINE_ON_PS3 bool CThread::Join( unsigned timeout )
+{
+#ifdef _WIN32
+ if ( m_hThread )
+#elif defined(POSIX)
+ if ( m_threadId || m_threadZombieId )
+#endif
+ {
+ AssertMsg(GetCurrentCThread() != this, _T("Thread cannot be joined with self"));
+
+#ifdef _WIN32
+ return ThreadJoin( (ThreadHandle_t)m_hThread, timeout );
+#elif defined(POSIX)
+ bool ret = ThreadJoin( (ThreadHandle_t)(m_threadId ? m_threadId : m_threadZombieId), timeout );
+ m_threadZombieId = 0;
+ return ret;
+#endif
+ }
+ return true;
+}
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 ThreadHandle_t CThread::GetThreadHandle()
+{
+#ifdef _WIN32
+ return (ThreadHandle_t)m_hThread;
+#else
+ return (ThreadHandle_t)m_threadId;
+#endif
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 int CThread::GetResult()
+{
+ return m_result;
+}
+
+//-----------------------------------------------------
+// Functions for both this, and maybe, and other threads
+//-----------------------------------------------------
+
+// Forcibly, abnormally, but relatively cleanly stop the thread
+//
+
+INLINE_ON_PS3 void CThread::Stop(int exitCode)
+{
+ if ( !IsAlive() )
+ return;
+
+ if ( GetCurrentCThread() == this )
+ {
+#if !defined( _PS3 )
+ m_result = exitCode;
+ if ( !( m_flags & SUPPORT_STOP_PROTOCOL ) )
+ {
+ OnExit();
+ g_pCurThread = NULL;
+
+#ifdef _WIN32
+ CloseHandle( m_hThread );
+ RemoveThreadHandleToIDMap( m_hThread );
+ m_hThread = NULL;
+#else
+ m_threadId = 0;
+ m_threadZombieId = 0;
+#endif
+ }
+ else
+ {
+ throw exitCode;
+ }
+#else
+ AssertMsg( false, "Called CThread::Stop() for a platform that doesn't have it!\n");
+#endif
+ }
+ else
+ AssertMsg( 0, "Only thread can stop self: Use a higher-level protocol");
+}
+
+//---------------------------------------------------------
+
+// Get the priority
+INLINE_ON_PS3 int CThread::GetPriority() const
+{
+#ifdef _WIN32
+ return GetThreadPriority(m_hThread);
+#elif defined( _PS3 )
+ return ThreadGetPriority( (ThreadHandle_t) m_threadId );
+#elif defined(POSIX)
+ struct sched_param thread_param;
+ int policy;
+ pthread_getschedparam( m_threadId, &policy, &thread_param );
+ return thread_param.sched_priority;
+#endif
+}
+
+//---------------------------------------------------------
+
+// Set the priority
+INLINE_ON_PS3 bool CThread::SetPriority(int priority)
+{
+#ifdef WIN32
+ return ThreadSetPriority( (ThreadHandle_t)m_hThread, priority );
+#else
+ return ThreadSetPriority( (ThreadHandle_t)m_threadId, priority );
+#endif
+}
+
+//---------------------------------------------------------
+
+// Suspend a thread
+INLINE_ON_PS3 unsigned CThread::Suspend()
+{
+ AssertMsg( ThreadGetCurrentId() == (ThreadId_t)m_threadId, "Cannot call CThread::Suspend from outside thread" );
+
+ if ( ThreadGetCurrentId() != (ThreadId_t)m_threadId )
+ {
+ DebuggerBreakIfDebugging();
+ }
+
+ m_NotSuspendedEvent.Reset();
+ m_NotSuspendedEvent.Wait();
+
+ return 0;
+}
+
+
+//---------------------------------------------------------
+
+INLINE_ON_PS3 unsigned CThread::Resume()
+{
+ if ( m_NotSuspendedEvent.Check() )
+ {
+ DevWarning( "Called Resume() on a thread that is not suspended!\n" );
+ }
+ m_NotSuspendedEvent.Set();
+ return 0;
+}
+
+//---------------------------------------------------------
+
+// Force hard-termination of thread. Used for critical failures.
+INLINE_ON_PS3 bool CThread::Terminate(int exitCode)
+{
+#if defined( _X360 )
+ AssertMsg( 0, "Cannot terminate a thread on the Xbox!" );
+ return false;
+#elif defined( _WIN32 )
+ // I hope you know what you're doing!
+ if (!TerminateThread(m_hThread, exitCode))
+ return false;
+ CloseHandle( m_hThread );
+ RemoveThreadHandleToIDMap( m_hThread );
+ m_hThread = NULL;
+#elif defined( _PS3 )
+ m_threadEnd.Set();
+ m_threadId = NULL;
+#elif defined(POSIX)
+ pthread_kill( m_threadId, SIGKILL );
+ m_threadId = 0;
+#endif
+ return true;
+}
+
+//-----------------------------------------------------
+// Global methods
+//-----------------------------------------------------
+
+// Get the Thread object that represents the current thread, if any.
+// Can return NULL if the current thread was not created using
+// CThread
+//
+
+INLINE_ON_PS3 CThread *CThread::GetCurrentCThread()
+{
+#ifdef _PS3
+ return GetCurThreadPS3();
+#else
+ return g_pCurThread;
+#endif
+}
+
+//---------------------------------------------------------
+//
+// Offer a context switch. Under Win32, equivalent to Sleep(0)
+//
+
+#ifdef Yield
+#undef Yield
+#endif
+INLINE_ON_PS3 void CThread::Yield()
+{
+#ifdef _WIN32
+ ::Sleep(0);
+#elif defined( _PS3 )
+ // sys_ppu_thread_yield doesn't seem to function properly, so sleep instead.
+ sys_timer_usleep( 60 );
+#elif defined(POSIX)
+ pthread_yield();
+#endif
+}
+
+//---------------------------------------------------------
+//
+// This method causes the current thread to yield and not to be
+// scheduled for further execution until a certain amount of real
+// time has elapsed, more or less. Duration is in milliseconds
+
+INLINE_ON_PS3 void CThread::Sleep( unsigned duration )
+{
+#ifdef _WIN32
+ ::Sleep(duration);
+#elif defined (_PS3)
+ sys_timer_usleep( duration * 1000 );
+#elif defined(POSIX)
+ usleep( duration * 1000 );
+#endif
+}
+
+//---------------------------------------------------------
+
+// Optional pre-run call, with ability to fail-create. Note Init()
+// is forced synchronous with Start()
+INLINE_ON_PS3 bool CThread::Init()
+{
+ return true;
+}
+
+//---------------------------------------------------------
+
+#if defined( _PS3 )
+INLINE_ON_PS3 int CThread::Run()
+{
+ return -1;
+}
+#endif // _PS3
+
+// Called when the thread exits
+INLINE_ON_PS3 void CThread::OnExit() { }
+
+// Allow for custom start waiting
+INLINE_ON_PS3 bool CThread::WaitForCreateComplete( CThreadEvent *pEvent )
+{
+ // Force serialized thread creation...
+ if (!pEvent->Wait(60000))
+ {
+ AssertMsg( 0, "Probably deadlock or failure waiting for thread to initialize." );
+ return false;
+ }
+ return true;
+}
+
+//---------------------------------------------------------
+INLINE_ON_PS3 CThread::ThreadProc_t CThread::GetThreadProc()
+{
+ return ThreadProc;
+}
+
+#ifdef PLATFORM_WINDOWS
+unsigned long STDCALL CThread::ThreadProc(LPVOID pv)
+#else
+INLINE_ON_PS3 void* CThread::ThreadProc(LPVOID pv)
+#endif
+{
+#if defined( POSIX ) || defined( _PS3 )
+ ThreadInit_t *pInit = reinterpret_cast<ThreadInit_t*>(pv);
+#else
+ std::auto_ptr<ThreadInit_t> pInit((ThreadInit_t *)pv);
+#endif
+
+#ifdef _X360
+ // Make sure all threads are consistent w.r.t floating-point math
+ SetupFPUControlWord();
+#endif
+ AllocateThreadID();
+
+ CThread *pThread = pInit->pThread;
+#ifdef _PS3
+ SetCurThreadPS3( pThread );
+#else
+ g_pCurThread = pThread;
+#endif
+
+ pThread->m_pStackBase = AlignValue( &pThread, 4096 );
+
+ pInit->pThread->m_result = -1;
+
+#if defined( THREAD_PARENT_STACK_TRACE_ENABLED )
+ CStackTop_ReferenceParentStack stackTop( pInit->ParentStackTrace, ARRAYSIZE( pInit->ParentStackTrace ) );
+#endif
+
+ bool bInitSuccess = true;
+ if ( pInit->pfInitSuccess )
+ *(pInit->pfInitSuccess) = false;
+
+#ifdef _PS3
+ *(pInit->pfInitSuccess) = pInit->pThread->Init();
+#else
+ try
+ {
+ bInitSuccess = pInit->pThread->Init();
+ }
+
+ catch (...)
+ {
+ pInit->pInitCompleteEvent->Set();
+ throw;
+ }
+#endif // _PS3
+
+ if ( pInit->pfInitSuccess )
+ *(pInit->pfInitSuccess) = bInitSuccess;
+ pInit->pInitCompleteEvent->Set();
+ if (!bInitSuccess)
+ return 0;
+
+ if ( !Plat_IsInDebugSession() && (pInit->pThread->m_flags & SUPPORT_STOP_PROTOCOL) )
+ {
+#ifndef _PS3
+ try
+#endif
+ {
+ pInit->pThread->m_result = pInit->pThread->Run();
+ }
+
+#ifndef _PS3
+ catch (...)
+ {
+ }
+#endif
+ }
+ else
+ {
+ pInit->pThread->m_result = pInit->pThread->Run();
+ }
+
+ pInit->pThread->OnExit();
+#ifdef _PS3
+ SetCurThreadPS3( NULL );
+#else
+ g_pCurThread = NULL;
+#endif
+ FreeThreadID();
+
+ AUTO_LOCK( pThread->m_Lock );
+#ifdef _WIN32
+ CloseHandle( pThread->m_hThread );
+ RemoveThreadHandleToIDMap( pThread->m_hThread );
+ pThread->m_hThread = NULL;
+#elif defined( _PS3 )
+ pThread->m_threadZombieId = pThread->m_threadId;
+ pThread->m_threadEnd.Set();
+ pThread->m_threadId = 0;
+#elif defined(POSIX)
+ pThread->m_threadZombieId = pThread->m_threadId;
+ pThread->m_threadId = 0;
+#else
+#error
+#endif
+
+ pThread->m_ExitEvent.Set();
+#ifdef _PS3
+ {
+ pThread->m_Lock.Unlock();
+ sys_ppu_thread_exit( pInit->pThread->m_result );
+ // reacquire the lock in case thread exit didn't actually exit the thread, so that
+ // AUTO_LOCK won't double-unlock the lock (to keep it paired)
+ pThread->m_Lock.Lock();
+ }
+#endif
+
+#if defined( POSIX )|| defined( _PS3 )
+ return (void*)pInit->pThread->m_result;
+#else
+ return pInit->pThread->m_result;
+#endif
+}
+
+#endif // THREADTOOLS_INL
diff --git a/external/vpc/public/tier0/tslist.h b/external/vpc/public/tier0/tslist.h
new file mode 100644
index 0000000..d8bc55e
--- /dev/null
+++ b/external/vpc/public/tier0/tslist.h
@@ -0,0 +1,858 @@
+//========== Copyright � 2005, Valve Corporation, All rights reserved. ========
+//
+// Purpose:
+//
+// LIFO from disassembly of Windows API and http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf
+// FIFO from http://perso.wanadoo.fr/gmem/evenements/jim2002/articles/L17_Fober.pdf
+//
+//=============================================================================
+
+#ifndef TSLIST_H
+#define TSLIST_H
+
+#if defined( _WIN32 )
+#pragma once
+#endif
+
+#if ( defined( PLATFORM_X360 ) || defined( PLATFORM_WINDOWS_PC64 ) )
+#define USE_NATIVE_SLIST
+#endif
+
+#if defined( USE_NATIVE_SLIST ) && !defined( _X360 ) && !defined( _PS3 )
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+
+#if defined(PLATFORM_WINDOWS_PC64)
+
+#define TSLIST_HEAD_ALIGNMENT 16 //MEMORY_ALLOCATION_ALIGNMENT
+#define TSLIST_NODE_ALIGNMENT 16 //MEMORY_ALLOCATION_ALIGNMENT
+
+#define TSLIST_HEAD_ALIGN ALIGN16
+#define TSLIST_NODE_ALIGN ALIGN16
+#define TSLIST_HEAD_ALIGN_POST ALIGN16_POST
+#define TSLIST_NODE_ALIGN_POST ALIGN16_POST
+
+#else
+
+#define TSLIST_HEAD_ALIGNMENT 8
+#define TSLIST_NODE_ALIGNMENT 8
+
+#define TSLIST_HEAD_ALIGN ALIGN8
+#define TSLIST_NODE_ALIGN ALIGN8
+#define TSLIST_HEAD_ALIGN_POST ALIGN8_POST
+#define TSLIST_NODE_ALIGN_POST ALIGN8_POST
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE bool RunTSQueueTests( int nListSize = 10000, int nTests = 1 );
+PLATFORM_INTERFACE bool RunTSListTests( int nListSize = 10000, int nTests = 1 );
+
+//-----------------------------------------------------------------------------
+// Lock free list.
+//-----------------------------------------------------------------------------
+//#define USE_NATIVE_SLIST
+
+#ifdef USE_NATIVE_SLIST
+typedef SLIST_ENTRY TSLNodeBase_t;
+typedef SLIST_HEADER TSLHead_t;
+#else
+struct TSLIST_NODE_ALIGN TSLNodeBase_t
+{
+ TSLNodeBase_t *Next; // name to match Windows
+}
+TSLIST_NODE_ALIGN_POST;
+
+union TSLHead_t
+{
+ struct Value_t
+ {
+ TSLNodeBase_t *Next;
+ // <sergiy> Depth must be in the least significant halfword when atomically loading into register,
+ // to avoid carrying digits from Sequence. Carrying digits from Depth to Sequence is ok,
+ // because Sequence can be pretty much random. We could operate on both of them separately,
+ // but it could perhaps (?) lead to problems with store forwarding. I don't know 'cause I didn't
+ // performance-test or design original code, I'm just making it work on PowerPC.
+ #ifdef PLAT_BIG_ENDIAN
+ int16 Sequence;
+ int16 Depth;
+ #else
+ int16 Depth;
+ int16 Sequence;
+ #endif
+ } value;
+
+ struct Value32_t
+ {
+ TSLNodeBase_t *Next_do_not_use_me;
+ int32 DepthAndSequence;
+ } value32;
+
+ int64 value64;
+};
+#endif
+
+//-------------------------------------
+
+class TSLIST_HEAD_ALIGN CTSListBase
+{
+public:
+ CTSListBase()
+ {
+ if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( _T( "CTSListBase: Misaligned list\n" ) );
+ DebuggerBreak();
+ }
+
+#ifdef USE_NATIVE_SLIST
+ InitializeSListHead( &m_Head );
+#else
+ m_Head.value64 = (int64)0;
+#endif
+ }
+
+ ~CTSListBase()
+ {
+ Detach();
+ }
+
+ TSLNodeBase_t *Push( TSLNodeBase_t *pNode )
+ {
+#ifdef _DEBUG
+ if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 )
+ {
+ Error( _T( "CTSListBase: Misaligned node\n" ) );
+ DebuggerBreak();
+ }
+#endif
+
+#ifdef USE_NATIVE_SLIST
+#ifdef _X360
+ // integrated write-release barrier
+ return (TSLNodeBase_t *)InterlockedPushEntrySListRelease( &m_Head, pNode );
+#else
+ return (TSLNodeBase_t *)InterlockedPushEntrySList( &m_Head, pNode );
+#endif
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ #if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
+ __lwsync(); // write-release barrier
+ #endif
+
+ for (;;)
+ {
+ oldHead.value64 = m_Head.value64;
+ pNode->Next = oldHead.value.Next;
+ newHead.value.Next = pNode;
+
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence + 0x10001;
+
+
+ if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) )
+ {
+ break;
+ }
+ ThreadPause();
+ };
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLNodeBase_t *Pop()
+ {
+#ifdef USE_NATIVE_SLIST
+#ifdef _X360
+ // integrated read-acquire barrier
+ TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySListAcquire( &m_Head );
+#else
+ TSLNodeBase_t *pNode = (TSLNodeBase_t *)InterlockedPopEntrySList( &m_Head );
+#endif
+ return pNode;
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ for (;;)
+ {
+ oldHead.value64 = m_Head.value64;
+ if ( !oldHead.value.Next )
+ return NULL;
+
+ newHead.value.Next = oldHead.value.Next->Next;
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
+
+
+ if ( ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) )
+ {
+ #if defined( PLATFORM_PS3 ) || defined( PLATFORM_X360 )
+ __lwsync(); // read-acquire barrier
+ #endif
+ break;
+ }
+ ThreadPause();
+ };
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLNodeBase_t *Detach()
+ {
+#ifdef USE_NATIVE_SLIST
+ TSLNodeBase_t *pBase = (TSLNodeBase_t *)InterlockedFlushSList( &m_Head );
+#if defined( _X360 ) || defined( _PS3 )
+ __lwsync(); // read-acquire barrier
+#endif
+ return pBase;
+#else
+ TSLHead_t oldHead;
+ TSLHead_t newHead;
+
+ do
+ {
+ ThreadPause();
+
+ oldHead.value64 = m_Head.value64;
+ if ( !oldHead.value.Next )
+ return NULL;
+
+ newHead.value.Next = NULL;
+ // <sergiy> the reason for AND'ing it instead of poking a short into memory
+ // is probably to avoid store forward issues, but I'm not sure because
+ // I didn't construct this code. In any case, leaving it as is on big-endian
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence & 0xffff0000;
+
+ } while( !ThreadInterlockedAssignIf64( &m_Head.value64, newHead.value64, oldHead.value64 ) );
+
+ return (TSLNodeBase_t *)oldHead.value.Next;
+#endif
+ }
+
+ TSLHead_t *AccessUnprotected()
+ {
+ return &m_Head;
+ }
+
+ int Count() const
+ {
+#ifdef USE_NATIVE_SLIST
+ return QueryDepthSList( const_cast<TSLHead_t*>( &m_Head ) );
+#else
+ return m_Head.value.Depth;
+#endif
+ }
+
+private:
+ TSLHead_t m_Head;
+}
+TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSSimpleList : public CTSListBase
+{
+public:
+ void Push( T *pNode )
+ {
+ Assert( sizeof(T) >= sizeof(TSLNodeBase_t) );
+ CTSListBase::Push( (TSLNodeBase_t *)pNode );
+ }
+
+ T *Pop()
+ {
+ return (T *)CTSListBase::Pop();
+ }
+}
+TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+// this is a replacement for CTSList<> and CObjectPool<> that does not
+// have a per-item, per-alloc new/delete overhead
+// similar to CTSSimpleList except that it allocates it's own pool objects
+// and frees them on destruct. Also it does not overlay the TSNodeBase_t memory
+// on T's memory
+template< class T >
+class TSLIST_HEAD_ALIGN CTSPool : public CTSListBase
+{
+ // packs the node and the item (T) into a single struct and pools those
+ struct TSLIST_NODE_ALIGN simpleTSPoolStruct_t : public TSLNodeBase_t
+ {
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+public:
+
+ ~CTSPool()
+ {
+ simpleTSPoolStruct_t *pNode = NULL;
+ while ( 1 )
+ {
+ pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop();
+ if ( !pNode )
+ break;
+ delete pNode;
+ }
+ }
+
+ void PutObject( T *pInfo )
+ {
+ char *pElem = (char *)pInfo;
+ pElem -= offsetof(simpleTSPoolStruct_t,elem);
+ simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)pElem;
+
+ CTSListBase::Push( pNode );
+ }
+
+ T *GetObject()
+ {
+ simpleTSPoolStruct_t *pNode = (simpleTSPoolStruct_t *)CTSListBase::Pop();
+ if ( !pNode )
+ {
+ pNode = new simpleTSPoolStruct_t;
+ }
+ return &pNode->elem;
+ }
+
+ // omg windows sdk - why do you #define GetObject()?
+ FORCEINLINE T *Get()
+ {
+ return GetObject();
+ }
+
+} TSLIST_HEAD_ALIGN_POST;
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSList : public CTSListBase
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ T elem;
+
+ } TSLIST_NODE_ALIGN_POST;
+
+ ~CTSList()
+ {
+ Purge();
+ }
+
+ void Purge()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ }
+
+ void RemoveAll()
+ {
+ Purge();
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+ return (Node_t *)CTSListBase::Push( pNode );
+ }
+
+ Node_t *Pop()
+ {
+ return (Node_t *)CTSListBase::Pop();
+ }
+
+ void PushItem( const T &init )
+ {
+ Push( new Node_t( init ) );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ delete pNode;
+ return true;
+ }
+
+ Node_t *Detach()
+ {
+ return (Node_t *)CTSListBase::Detach();
+ }
+
+} TSLIST_HEAD_ALIGN_POST;
+
+//-------------------------------------
+
+template <typename T>
+class TSLIST_HEAD_ALIGN CTSListWithFreeList : public CTSListBase
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t : public TSLNodeBase_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+ ~CTSListWithFreeList()
+ {
+ Purge();
+ }
+
+ void Purge()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ pCurrent = (Node_t *)m_FreeList.Detach();
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ delete pCurrent;
+ pCurrent = pNext;
+ }
+ }
+
+ void RemoveAll()
+ {
+ Node_t *pCurrent = Detach();
+ Node_t *pNext;
+ while ( pCurrent )
+ {
+ pNext = (Node_t *)pCurrent->Next;
+ m_FreeList.Push( pCurrent );
+ pCurrent = pNext;
+ }
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+ return (Node_t *)CTSListBase::Push( pNode );
+ }
+
+ Node_t *Pop()
+ {
+ return (Node_t *)CTSListBase::Pop();
+ }
+
+ void PushItem( const T &init )
+ {
+ Node_t *pNode = (Node_t *)m_FreeList.Pop();
+ if ( !pNode )
+ {
+ pNode = new Node_t;
+ }
+ pNode->elem = init;
+ Push( pNode );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ m_FreeList.Push( pNode );
+ return true;
+ }
+
+ Node_t *Detach()
+ {
+ return (Node_t *)CTSListBase::Detach();
+ }
+
+ void FreeNode( Node_t *pNode )
+ {
+ m_FreeList.Push( pNode );
+ }
+
+private:
+ CTSListBase m_FreeList;
+} TSLIST_HEAD_ALIGN_POST;
+
+//-----------------------------------------------------------------------------
+// Lock free queue
+//
+// A special consideration: the element type should be simple. This code
+// actually dereferences freed nodes as part of pop, but later detects
+// that. If the item in the queue is a complex type, only bad things can
+// come of that. Also, therefore, if you're using Push/Pop instead of
+// push item, be aware that the node memory cannot be freed until
+// all threads that might have been popping have completed the pop.
+// The PushItem()/PopItem() for handles this by keeping a persistent
+// free list. Dont mix Push/PushItem. Note also nodes will be freed at the end,
+// and are expected to have been allocated with operator new.
+//-----------------------------------------------------------------------------
+
+template <typename T, bool bTestOptimizer = false, bool bFreeList = true>
+class TSLIST_HEAD_ALIGN CTSQueue
+{
+public:
+ struct TSLIST_NODE_ALIGN Node_t
+ {
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ Node_t *pNext;
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+ union TSLIST_HEAD_ALIGN NodeLink_t
+ {
+ struct Value_t
+ {
+ Node_t *pNode;
+ int32 sequence;
+ } value;
+
+ int64 value64;
+ } TSLIST_HEAD_ALIGN_POST;
+
+ CTSQueue()
+ {
+ COMPILE_TIME_ASSERT( sizeof(Node_t) >= sizeof(TSLNodeBase_t) );
+ if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( "CTSQueue: Misaligned queue\n" );
+ DebuggerBreak();
+ }
+ if ( ((size_t)&m_Tail) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( "CTSQueue: Misaligned queue\n" );
+ DebuggerBreak();
+ }
+ m_Count = 0;
+ m_Head.value.sequence = m_Tail.value.sequence = 0;
+ m_Head.value.pNode = m_Tail.value.pNode = new Node_t; // list always contains a dummy node
+ m_Head.value.pNode->pNext = End();
+ }
+
+ ~CTSQueue()
+ {
+ Purge();
+ Assert( m_Count == 0 );
+ Assert( m_Head.value.pNode == m_Tail.value.pNode );
+ Assert( m_Head.value.pNode->pNext == End() );
+ delete m_Head.value.pNode;
+ }
+
+ // Note: Purge, RemoveAll, and Validate are *not* threadsafe
+ void Purge()
+ {
+ if ( IsDebug() )
+ {
+ Validate();
+ }
+
+ Node_t *pNode;
+ while ( ( pNode = Pop() ) != NULL )
+ {
+ delete pNode;
+ }
+
+ while ( bFreeList && ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
+ {
+ delete pNode;
+ }
+
+ Assert( m_Count == 0 );
+ Assert( m_Head.value.pNode == m_Tail.value.pNode );
+ Assert( m_Head.value.pNode->pNext == End() );
+
+ m_Head.value.sequence = m_Tail.value.sequence = 0;
+ }
+
+ void RemoveAll()
+ {
+ if ( IsDebug() )
+ {
+ Validate();
+ }
+
+ Node_t *pNode;
+ while ( bFreeList && ( pNode = Pop() ) != NULL )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ }
+
+ bool Validate()
+ {
+ bool bResult = true;
+ int nNodes = 0;
+
+ if ( m_Count == 0 )
+ {
+ if ( m_Head.value.pNode != m_Tail.value.pNode )
+ {
+ DebuggerBreakIfDebugging();
+ bResult = false;
+ }
+ }
+
+ Node_t *pNode = m_Head.value.pNode;
+ while ( pNode != End() )
+ {
+ nNodes++;
+ pNode = pNode->pNext;
+ }
+
+ nNodes--;// skip dummy node
+
+ if ( nNodes != m_Count )
+ {
+ DebuggerBreakIfDebugging();
+ bResult = false;
+ }
+
+ if ( !bResult )
+ {
+ Msg( "Corrupt CTSQueueDetected" );
+ }
+
+ return bResult;
+ }
+
+ void FinishPush( Node_t *pNode, const NodeLink_t &oldTail )
+ {
+ NodeLink_t newTail;
+
+ newTail.value.pNode = pNode;
+ newTail.value.sequence = oldTail.value.sequence + 1;
+
+ ThreadMemoryBarrier();
+
+ InterlockedCompareExchangeNodeLink( &m_Tail, newTail, oldTail );
+ }
+
+ Node_t *Push( Node_t *pNode )
+ {
+#ifdef _DEBUG
+ if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 )
+ {
+ Error( "CTSListBase: Misaligned node\n" );
+ DebuggerBreak();
+ }
+#endif
+
+ NodeLink_t oldTail;
+
+ pNode->pNext = End();
+
+ for (;;)
+ {
+ oldTail.value.sequence = m_Tail.value.sequence;
+ oldTail.value.pNode = m_Tail.value.pNode;
+ if ( InterlockedCompareExchangeNode( &(oldTail.value.pNode->pNext), pNode, End() ) == End() )
+ {
+ break;
+ }
+ else
+ {
+ // Another thread is trying to push, help it along
+ FinishPush( oldTail.value.pNode->pNext, oldTail );
+ }
+ }
+
+ FinishPush( pNode, oldTail ); // This can fail if another thread pushed between the sequence and node grabs above. Later pushes or pops corrects
+
+ m_Count++;
+
+ return oldTail.value.pNode;
+ }
+
+ Node_t *Pop()
+ {
+ #define TSQUEUE_BAD_NODE_LINK ( (Node_t *)INT_TO_POINTER( 0xdeadbeef ) )
+ NodeLink_t * volatile pHead = &m_Head;
+ NodeLink_t * volatile pTail = &m_Tail;
+ Node_t * volatile * pHeadNode = &m_Head.value.pNode;
+ volatile int * volatile pHeadSequence = &m_Head.value.sequence;
+ Node_t * volatile * pTailNode = &pTail->value.pNode;
+
+ NodeLink_t head;
+ NodeLink_t newHead;
+ Node_t *pNext;
+ int tailSequence;
+ T elem;
+
+ for (;;)
+ {
+ head.value.sequence = *pHeadSequence; // must grab sequence first, which allows condition below to ensure pNext is valid
+ ThreadMemoryBarrier(); // need a barrier to prevent reordering of these assignments
+ head.value.pNode = *pHeadNode;
+ tailSequence = pTail->value.sequence;
+ pNext = head.value.pNode->pNext;
+
+ if ( pNext && head.value.sequence == *pHeadSequence ) // Checking pNext only to force optimizer to not reorder the assignment to pNext and the compare of the sequence
+ {
+ if ( bTestOptimizer )
+ {
+ if ( pNext == TSQUEUE_BAD_NODE_LINK )
+ {
+ Msg( "Bad node link detected\n" );
+ continue;
+ }
+ }
+ if ( head.value.pNode == *pTailNode )
+ {
+ if ( pNext == End() )
+ {
+ return NULL;
+ }
+
+ // Another thread is trying to push, help it along
+ NodeLink_t &oldTail = head; // just reuse local memory for head to build old tail
+ oldTail.value.sequence = tailSequence; // reuse head pNode
+ FinishPush( pNext, oldTail );
+ }
+ else if ( pNext != End() )
+ {
+ elem = pNext->elem; // NOTE: next could be a freed node here, by design
+ newHead.value.pNode = pNext;
+ newHead.value.sequence = head.value.sequence + 1;
+ if ( InterlockedCompareExchangeNodeLink( pHead, newHead, head ) )
+ {
+ ThreadMemoryBarrier();
+
+ if ( bTestOptimizer )
+ {
+ head.value.pNode->pNext = TSQUEUE_BAD_NODE_LINK;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ m_Count--;
+ head.value.pNode->elem = elem;
+ return head.value.pNode;
+ }
+
+ void FreeNode( Node_t *pNode )
+ {
+ if ( bFreeList )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ else
+ {
+ delete pNode;
+ }
+ }
+
+ void PushItem( const T &init )
+ {
+ Node_t *pNode;
+ if ( bFreeList && ( pNode = (Node_t *)m_FreeNodes.Pop() ) != NULL )
+ {
+ pNode->elem = init;
+ }
+ else
+ {
+ pNode = new Node_t( init );
+ }
+ Push( pNode );
+ }
+
+ bool PopItem( T *pResult)
+ {
+ Node_t *pNode = Pop();
+ if ( !pNode )
+ return false;
+ *pResult = pNode->elem;
+ if ( bFreeList )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ else
+ {
+ delete pNode;
+ }
+ return true;
+ }
+
+ int Count()
+ {
+ return m_Count;
+ }
+
+private:
+ Node_t *End() { return (Node_t *)this; } // just need a unique signifier
+
+#ifndef _WIN64
+ Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand )
+ {
+ return (Node_t *)::ThreadInterlockedCompareExchangePointer( (void **)ppNode, value, comperand );
+ }
+
+ bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand )
+ {
+ return ThreadInterlockedAssignIf64( (int64 *)pLink, value.value64, comperand.value64 );
+ }
+
+#else
+ Node_t *InterlockedCompareExchangeNode( Node_t * volatile *ppNode, Node_t *value, Node_t *comperand )
+ {
+ AUTO_LOCK( m_ExchangeMutex );
+ Node_t *retVal = *ppNode;
+ if ( *ppNode == comperand )
+ *ppNode = value;
+ return retVal;
+ }
+
+ bool InterlockedCompareExchangeNodeLink( NodeLink_t volatile *pLink, const NodeLink_t &value, const NodeLink_t &comperand )
+ {
+ AUTO_LOCK( m_ExchangeMutex );
+ if ( pLink->value64 == comperand.value64 )
+ {
+ pLink->value64 = value.value64;
+ return true;
+ }
+ return false;
+ }
+
+ CThreadFastMutex m_ExchangeMutex;
+#endif
+
+ NodeLink_t m_Head;
+ NodeLink_t m_Tail;
+
+ CInterlockedInt m_Count;
+
+ CTSListBase m_FreeNodes;
+} TSLIST_HEAD_ALIGN_POST;
+
+#include "tier0/memdbgoff.h"
+
+#endif // TSLIST_H
diff --git a/external/vpc/public/tier0/validator.h b/external/vpc/public/tier0/validator.h
new file mode 100644
index 0000000..a3b336e
--- /dev/null
+++ b/external/vpc/public/tier0/validator.h
@@ -0,0 +1,73 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#include "valobject.h"
+
+#ifndef VALIDATOR_H
+#define VALIDATOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifdef DBGFLAG_VALIDATE
+
+
+class CValidator
+{
+public:
+ // Constructors & destructors
+ CValidator( void );
+ ~CValidator( void );
+
+ // Call this each time we enter a new Validate function
+ void Push( tchar *pchType, void *pvObj, tchar *pchName );
+
+ // Call this each time we exit a Validate function
+ void Pop( void );
+
+ // Claim ownership of a memory block
+ void ClaimMemory( void *pvMem );
+
+ // Finish performing a check and perform necessary computations
+ void Finalize( void );
+
+ // Render our results to the console
+ void RenderObjects( int cubThreshold ); // Render all reported objects
+ void RenderLeaks( void ); // Render all memory leaks
+
+ // List manipulation functions:
+ CValObject *FindObject( void *pvObj ); // Returns CValObject containing pvObj, or NULL.
+ void DiffAgainst( CValidator *pOtherValidator ); // Removes any entries from this validator that are also present in the other.
+
+ // Accessors
+ bool BMemLeaks( void ) { return m_bMemLeaks; };
+ CValObject *PValObjectFirst( void ) { return m_pValObjectFirst; };
+
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+
+
+private:
+ CValObject *m_pValObjectFirst; // Linked list of all ValObjects
+ CValObject *m_pValObjectLast; // Last ValObject on the linked list
+
+ CValObject *m_pValObjectCur; // Object we're current processing
+
+ int m_cpvOwned; // Total # of blocks owned
+
+ int m_cpubLeaked; // # of leaked memory blocks
+ int m_cubLeaked; // Amount of leaked memory
+ bool m_bMemLeaks; // Has any memory leaked?
+};
+
+
+#endif // DBGFLAG_VALIDATE
+
+
+#endif // VALIDATOR_H
diff --git a/external/vpc/public/tier0/valobject.h b/external/vpc/public/tier0/valobject.h
new file mode 100644
index 0000000..8a2cbf0
--- /dev/null
+++ b/external/vpc/public/tier0/valobject.h
@@ -0,0 +1,72 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: CValObject is used for tracking individual objects that report
+// in to CValidator. Whenever a new object reports in (via CValidator::Push),
+// we create a new CValObject to aggregate stats for it.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VALOBJECT_H
+#define VALOBJECT_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#ifdef DBGFLAG_VALIDATE
+class CValObject
+{
+public:
+ // Constructors & destructors
+ CValObject( void ) { };
+ ~CValObject( void );
+
+ void Init( tchar *pchType, void *pvObj, tchar *pchName, CValObject *pValObjectParent,
+ CValObject *pValObjectPrev );
+
+ // Our object has claimed ownership of a memory block
+ void ClaimMemoryBlock( void *pvMem );
+
+ // A child of ours has claimed ownership of a memory block
+ void ClaimChildMemoryBlock( int cubUser );
+
+ // Accessors
+ tchar *PchType( void ) { return m_rgchType; };
+ void *PvObj( void ) { return m_pvObj; };
+ tchar *PchName( void ) { return m_rgchName; };
+ CValObject *PValObjectParent( void ) { return m_pValObjectParent; };
+ int NLevel( void ) { return m_nLevel; };
+ CValObject *PValObjectNext( void ) { return m_pValObjectNext; };
+ int CpubMemSelf( void ) { return m_cpubMemSelf; };
+ int CubMemSelf( void ) { return m_cubMemSelf; };
+ int CpubMemTree( void ) { return m_cpubMemTree; };
+ int CubMemTree( void ) { return m_cubMemTree; };
+ int NUser( void ) { return m_nUser; };
+ void SetNUser( int nUser ) { m_nUser = nUser; };
+ void SetBNewSinceSnapshot( bool bNewSinceSnapshot ) { m_bNewSinceSnapshot = bNewSinceSnapshot; }
+ bool BNewSinceSnapshot( void ) { return m_bNewSinceSnapshot; }
+
+private:
+ bool m_bNewSinceSnapshot; // If this block is new since the snapshot.
+ tchar m_rgchType[64]; // Type of the object we represent
+ tchar m_rgchName[64]; // Name of this particular object
+ void *m_pvObj; // Pointer to the object we represent
+
+ CValObject *m_pValObjectParent; // Our parent object in the tree.
+ int m_nLevel; // Our depth in the tree
+
+ CValObject *m_pValObjectNext; // Next ValObject in the linked list
+
+ int m_cpubMemSelf; // # of memory blocks we own directly
+ int m_cubMemSelf; // Total size of the memory blocks we own directly
+
+ int m_cpubMemTree; // # of memory blocks owned by us and our children
+ int m_cubMemTree; // Total size of the memory blocks owned by us and our children
+
+ int m_nUser; // Field provided for use by our users
+};
+#endif // DBGFLAG_VALIDATE
+
+
+#endif // VALOBJECT_H
diff --git a/external/vpc/public/tier0/valve_off.h b/external/vpc/public/tier0/valve_off.h
new file mode 100644
index 0000000..954a140
--- /dev/null
+++ b/external/vpc/public/tier0/valve_off.h
@@ -0,0 +1,33 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This turns off all Valve-specific #defines. Because we sometimes
+// call external include files from inside .cpp files, we need to
+// wrap those includes like this:
+// #include "tier0/valve_off.h"
+// #include <external.h>
+// #include "tier0/valve_on.h"
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifdef STEAM
+
+//-----------------------------------------------------------------------------
+// Unicode-related #defines (see wchartypes.h)
+//-----------------------------------------------------------------------------
+#undef char
+
+
+//-----------------------------------------------------------------------------
+// Memory-related #defines
+//-----------------------------------------------------------------------------
+#undef malloc
+#undef realloc
+#undef _expand
+#undef free
+
+#endif // STEAM
+
+// Allow long to be used in 3rd-party headers
+#undef long \ No newline at end of file
diff --git a/external/vpc/public/tier0/valve_on.h b/external/vpc/public/tier0/valve_on.h
new file mode 100644
index 0000000..03ab0a7
--- /dev/null
+++ b/external/vpc/public/tier0/valve_on.h
@@ -0,0 +1,37 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: This turns on all Valve-specific #defines. Because we sometimes
+// call external include files from inside .cpp files, we need to
+// wrap those includes like this:
+// #include "tier0/valve_off.h"
+// #include <external.h>
+// #include "tier0/valve_on.h"
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifdef STEAM
+//-----------------------------------------------------------------------------
+// Unicode-related #defines (see wchartypes.h)
+//-----------------------------------------------------------------------------
+#ifdef ENFORCE_WCHAR
+#define char DontUseChar_SeeWcharOn.h
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Memory-related #defines
+//-----------------------------------------------------------------------------
+#define malloc( cub ) HEY_DONT_USE_MALLOC_USE_PVALLOC
+#define realloc( pvOld, cub ) HEY_DONT_USE_REALLOC_USE_PVREALLOC
+#define _expand( pvOld, cub ) HEY_DONT_USE_EXPAND_USE_PVEXPAND
+#define free( pv ) HEY_DONT_USE_FREE_USE_FREEPV
+
+#endif
+
+
+// Long is evil because it's treated differently by different compilers
+#ifdef DISALLOW_USE_OF_LONG
+ #define long long_is_the_devil_stop_using_it_use_int32_or_int64
+#endif
diff --git a/external/vpc/public/tier0/vprof.h b/external/vpc/public/tier0/vprof.h
new file mode 100644
index 0000000..5208e21
--- /dev/null
+++ b/external/vpc/public/tier0/vprof.h
@@ -0,0 +1,1510 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Real-Time Hierarchical Profiling
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VPROF_H
+#define VPROF_H
+
+#include "tier0/dbg.h"
+#include "tier0/fasttimer.h"
+#include "tier0/l2cache.h"
+#include "tier0/threadtools.h"
+#include "tier0/vprof_sn.h"
+
+// VProf is enabled by default in all configurations -except- X360 Retail.
+#if !( defined( _GAMECONSOLE ) && defined( _CERT ) )
+#define VPROF_ENABLED
+#endif
+
+#if defined(_X360) && defined(VPROF_ENABLED)
+
+// PIX is always enabled in PROFILE build on X360
+#ifdef PROFILE
+#define VPROF_PIX 1
+#endif
+
+#include "tier0/pmc360.h"
+#ifndef USE_PIX
+#define VPROF_UNDO_PIX
+#undef _PIX_H_
+#undef PIXBeginNamedEvent
+#undef PIXEndNamedEvent
+#undef PIXSetMarker
+#undef PIXNameThread
+#define USE_PIX
+#include <pix.h>
+#undef USE_PIX
+#else
+#include <pix.h>
+#endif
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
+// enable this to get detailed nodes beneath budget
+//#define VPROF_LEVEL 1
+
+#if defined(_X360) || defined(_PS3)
+#define VPROF_VXCONSOLE_EXISTS 1
+#endif
+
+#if defined(_X360) && defined(VPROF_PIX)
+#pragma comment( lib, "Xapilibi" )
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Profiling instrumentation macros
+//
+
+#define MAXCOUNTERS 256
+
+
+#ifdef VPROF_ENABLED
+
+#define VPROF_VTUNE_GROUP
+
+#define VPROF( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0)
+#define VPROF_ASSERT_ACCOUNTED( name ) VPROF_(name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, true, 0)
+#define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail(name,group, bAssertAccounted, budgetFlags)
+
+#define VPROF_BUDGET( name, group ) VPROF_BUDGET_FLAGS(name, group, BUDGETFLAG_OTHER)
+#define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF_(name, 0, group, false, flags)
+
+#define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag )
+#define VPROF_SCOPE_END() } while (0)
+
+#define VPROF_ONLY( expression ) ( expression )
+
+#define VPROF_ENTER_SCOPE( name ) g_VProfCurrentProfile.EnterScope( name, 1, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0 )
+#define VPROF_EXIT_SCOPE() g_VProfCurrentProfile.ExitScope()
+
+#define VPROF_BUDGET_GROUP_ID_UNACCOUNTED 0
+
+
+// Budgetgroup flags. These are used with VPROF_BUDGET_FLAGS.
+// These control which budget panels the groups show up in.
+// If a budget group uses VPROF_BUDGET, it gets the default
+// which is BUDGETFLAG_OTHER.
+#define BUDGETFLAG_CLIENT (1<<0) // Shows up in the client panel.
+#define BUDGETFLAG_SERVER (1<<1) // Shows up in the server panel.
+#define BUDGETFLAG_OTHER (1<<2) // Unclassified (the client shows these but the dedicated server doesn't).
+#define BUDGETFLAG_HIDDEN (1<<15)
+#define BUDGETFLAG_ALL 0xFFFF
+
+
+// NOTE: You can use strings instead of these defines. . they are defined here and added
+// in vprof.cpp so that they are always in the same order.
+#define VPROF_BUDGETGROUP_OTHER_UNACCOUNTED _T("Unaccounted")
+#define VPROF_BUDGETGROUP_WORLD_RENDERING _T("World Rendering")
+#define VPROF_BUDGETGROUP_DISPLACEMENT_RENDERING _T("Displacement_Rendering")
+#define VPROF_BUDGETGROUP_GAME _T("Game")
+#define VPROF_BUDGETGROUP_NPCS _T("NPCs")
+#define VPROF_BUDGETGROUP_SERVER_ANIM _T("Server Animation")
+#define VPROF_BUDGETGROUP_PHYSICS _T("Physics")
+#define VPROF_BUDGETGROUP_STATICPROP_RENDERING _T("Static_Prop_Rendering")
+#define VPROF_BUDGETGROUP_MODEL_RENDERING _T("Other_Model_Rendering")
+#define VPROF_BUDGETGROUP_MODEL_FAST_PATH_RENDERING _T("Fast Path Model Rendering")
+#define VPROF_BUDGETGROUP_BRUSH_FAST_PATH_RENDERING _T("Fast Path Brush Rendering")
+#define VPROF_BUDGETGROUP_BRUSHMODEL_RENDERING _T("Brush_Model_Rendering")
+#define VPROF_BUDGETGROUP_SHADOW_RENDERING _T("Shadow_Rendering")
+#define VPROF_BUDGETGROUP_DETAILPROP_RENDERING _T("Detail_Prop_Rendering")
+#define VPROF_BUDGETGROUP_PARTICLE_RENDERING _T("Particle/Effect_Rendering")
+#define VPROF_BUDGETGROUP_ROPES _T("Ropes")
+#define VPROF_BUDGETGROUP_DLIGHT_RENDERING _T("Dynamic_Light_Rendering")
+#define VPROF_BUDGETGROUP_OTHER_NETWORKING _T("Networking")
+#define VPROF_BUDGETGROUP_CLIENT_ANIMATION _T("Client_Animation")
+#define VPROF_BUDGETGROUP_OTHER_SOUND _T("Sound")
+#define VPROF_BUDGETGROUP_OTHER_VGUI _T("VGUI")
+#define VPROF_BUDGETGROUP_OTHER_FILESYSTEM _T("FileSystem")
+#define VPROF_BUDGETGROUP_PREDICTION _T("Prediction")
+#define VPROF_BUDGETGROUP_INTERPOLATION _T("Interpolation")
+#define VPROF_BUDGETGROUP_SWAP_BUFFERS _T("Swap_Buffers")
+#define VPROF_BUDGETGROUP_PLAYER _T("Player")
+#define VPROF_BUDGETGROUP_OCCLUSION _T("Occlusion")
+#define VPROF_BUDGETGROUP_OVERLAYS _T("Overlays")
+#define VPROF_BUDGETGROUP_TOOLS _T("Tools")
+#define VPROF_BUDGETGROUP_LIGHTCACHE _T("Light_Cache")
+#define VPROF_BUDGETGROUP_DISP_HULLTRACES _T("Displacement_Hull_Traces")
+#define VPROF_BUDGETGROUP_TEXTURE_CACHE _T("Texture_Cache")
+#define VPROF_BUDGETGROUP_REPLAY _T("Replay")
+#define VPROF_BUDGETGROUP_PARTICLE_SIMULATION _T("Particle Simulation")
+#define VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING _T("Flashlight Shadows")
+#define VPROF_BUDGETGROUP_CLIENT_SIM _T("Client Simulation") // think functions, tempents, etc.
+#define VPROF_BUDGETGROUP_STEAM _T("Steam")
+#define VPROF_BUDGETGROUP_CVAR_FIND _T("Cvar_Find")
+#define VPROF_BUDGETGROUP_CLIENTLEAFSYSTEM _T("ClientLeafSystem")
+#define VPROF_BUDGETGROUP_JOBS_COROUTINES _T("Jobs/Coroutines")
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+// update flags
+#define VPROF_UPDATE_BUDGET 0x01 // send budget data every frame
+#define VPROF_UPDATE_TEXTURE_GLOBAL 0x02 // send global texture data every frame
+#define VPROF_UPDATE_TEXTURE_PERFRAME 0x04 // send perframe texture data every frame
+#endif
+
+//-------------------------------------
+
+#ifndef VPROF_LEVEL
+#define VPROF_LEVEL 0
+#endif
+
+#if !defined( VPROF_SN_LEVEL ) && !defined( _CERT )
+#define VPROF_SN_LEVEL 0
+#endif
+
+#define VPROF_0(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 0, group, assertAccounted, budgetFlags);
+
+#if VPROF_LEVEL > 0
+# define VPROF_1(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 1, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 0 && defined( _PS3 )
+# define VPROF_1(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 1
+#define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 2, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 1 && defined( _PS3 )
+# define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 2
+#define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 3, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 2 && defined( _PS3 )
+# define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+#if VPROF_LEVEL > 3
+#define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfScope VProf_(name, 4, group, assertAccounted, budgetFlags);
+#else
+# if VPROF_SN_LEVEL > 3 && defined( _PS3 )
+# define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfSnMarkerScope VProfSn_( name )
+# else
+# define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+#endif
+
+//-------------------------------------
+
+#ifdef _MSC_VER
+#define VProfCode( code ) \
+ if ( 0 ) \
+ ; \
+ else \
+ { \
+ VPROF( __FUNCTION__ ": " #code ); \
+ code; \
+ }
+#else
+#define VProfCode( code ) \
+ if ( 0 ) \
+ ; \
+ else \
+ { \
+ VPROF( #code ); \
+ code; \
+ }
+#endif
+
+
+//-------------------------------------
+
+#define VPROF_INCREMENT_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Increment( amount ); } while( 0 )
+#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Increment( amount ); } while( 0 )
+#define VPROF_SET_COUNTER(name,amount) do { static CVProfCounter _counter( name ); _counter.Set( amount ); } while( 0 )
+#define VPROF_SET_GROUP_COUNTER(name,group,amount) do { static CVProfCounter _counter( name, group ); _counter.Set( amount ); } while( 0 )
+
+#else
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 0 )
+# define VPROF( name ) CVProfSnMarkerScope VProfSn_( name )
+# define VPROF_ASSERT_ACCOUNTED( name ) VPROF( name )
+# define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) VPROF_##detail( name, group, bAssertAccounted, budgetFlags )
+# define VPROF_0(name,group,assertAccounted,budgetFlags) VPROF( name )
+# define VPROF_BUDGET( name, group ) VPROF( name )
+# define VPROF_BUDGET_FLAGS( name, group, flags ) VPROF( name )
+
+# define VPROF_SCOPE_BEGIN( tag ) do { VPROF( tag )
+# define VPROF_SCOPE_END() } while (0)
+
+# define VPROF_ONLY( expression ) ( expression )
+
+# define VPROF_ENTER_SCOPE( name ) g_pfnPushMarker( name )
+# define VPROF_EXIT_SCOPE() g_pfnPopMarker()
+# else
+# define VPROF( name ) ((void)0)
+# define VPROF_ASSERT_ACCOUNTED( name ) ((void)0)
+# define VPROF_( name, detail, group, bAssertAccounted, budgetFlags ) ((void)0)
+# define VPROF_0(name,group,assertAccounted,budgetFlags) ((void)0)
+# define VPROF_BUDGET( name, group ) ((void)0)
+# define VPROF_BUDGET_FLAGS( name, group, flags ) ((void)0)
+
+# define VPROF_SCOPE_BEGIN( tag ) do {
+# define VPROF_SCOPE_END() } while (0)
+
+# define VPROF_ONLY( expression ) ((void)0)
+
+# define VPROF_ENTER_SCOPE( name )
+# define VPROF_EXIT_SCOPE()
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 1 )
+# define VPROF_1(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 2 )
+# define VPROF_2(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 3 )
+# define VPROF_3(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+# if defined( VPROF_SN_LEVEL ) && ( VPROF_SN_LEVEL >= 4 )
+# define VPROF_4(name,group,assertAccounted,budgetFlags) VPROF( name )
+# else
+# define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
+# endif
+
+
+
+#define VPROF_INCREMENT_COUNTER(name,amount) ((void)0)
+#define VPROF_INCREMENT_GROUP_COUNTER(name,group,amount) ((void)0)
+#define VPROF_SET_COUNTER(name,amount) ((void)0)
+#define VPROF_SET_GROUP_COUNTER(name,group,amount) ((void)0)
+
+#define VPROF_TEST_SPIKE( msec ) ((void)0)
+
+#define VProfCode( code ) code
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#ifdef VPROF_ENABLED
+
+//-----------------------------------------------------------------------------
+//
+// A node in the call graph hierarchy
+//
+
+class PLATFORM_CLASS CVProfNode
+{
+friend class CVProfRecorder;
+friend class CVProfile;
+
+public:
+ CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags );
+ ~CVProfNode();
+
+ CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, int budgetFlags );
+ CVProfNode *GetSubNode( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName );
+ CVProfNode *GetParent();
+ CVProfNode *GetSibling();
+ CVProfNode *GetPrevSibling();
+ CVProfNode *GetChild();
+
+ void MarkFrame();
+ void ResetPeak();
+
+ void Pause();
+ void Resume();
+ void Reset();
+
+ void EnterScope();
+ bool ExitScope();
+
+ const tchar *GetName();
+
+ int GetBudgetGroupID()
+ {
+ return m_BudgetGroupID;
+ }
+
+ // Only used by the record/playback stuff.
+ void SetBudgetGroupID( int id )
+ {
+ m_BudgetGroupID = id;
+ }
+
+ int GetCurCalls();
+ double GetCurTime();
+ int GetPrevCalls();
+ double GetPrevTime();
+ int GetTotalCalls();
+ double GetTotalTime();
+ double GetPeakTime();
+
+ double GetCurTimeLessChildren();
+ double GetPrevTimeLessChildren();
+ double GetTotalTimeLessChildren();
+
+ int GetPrevL2CacheMissLessChildren();
+ int GetPrevLoadHitStoreLessChildren();
+
+ void ClearPrevTime();
+
+ int GetL2CacheMisses();
+
+ // Not used in the common case...
+ void SetCurFrameTime( unsigned long milliseconds );
+
+ void SetClientData( int iClientData ) { m_iClientData = iClientData; }
+ int GetClientData() const { return m_iClientData; }
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+
+// Used by vprof record/playback.
+private:
+
+ void SetUniqueNodeID( int id )
+ {
+ m_iUniqueNodeID = id;
+ }
+
+ int GetUniqueNodeID() const
+ {
+ return m_iUniqueNodeID;
+ }
+
+ static int s_iCurrentUniqueNodeID;
+
+
+private:
+ const tchar *m_pszName;
+ CFastTimer m_Timer;
+
+ // L2 Cache data.
+ int m_iPrevL2CacheMiss;
+ int m_iCurL2CacheMiss;
+ int m_iTotalL2CacheMiss;
+
+#ifndef _X360
+ // L2 Cache data.
+ CL2Cache m_L2Cache;
+#else // 360:
+
+ unsigned int m_iBitFlags; // see enum below for settings
+ CPMCData m_PMCData;
+ int m_iPrevLoadHitStores;
+ int m_iCurLoadHitStores;
+ int m_iTotalLoadHitStores;
+
+ public:
+ enum FlagBits
+ {
+ kRecordL2 = 0x01,
+ kCPUTrace = 0x02, ///< cause a PIX trace inside this node.
+ };
+ // call w/ true to enable L2 and LHS recording; false to turn it off
+ inline void EnableL2andLHS(bool enable)
+ {
+ if (enable)
+ m_iBitFlags |= kRecordL2;
+ else
+ m_iBitFlags &= (~kRecordL2);
+ }
+
+ inline bool IsL2andLHSEnabled( void )
+ {
+ return (m_iBitFlags & kRecordL2) != 0;
+ }
+
+ int GetLoadHitStores();
+
+ private:
+
+#endif
+
+ int m_nRecursions;
+
+ unsigned m_nCurFrameCalls;
+ CCycleCount m_CurFrameTime;
+
+ unsigned m_nPrevFrameCalls;
+ CCycleCount m_PrevFrameTime;
+
+ unsigned m_nTotalCalls;
+ CCycleCount m_TotalTime;
+
+ CCycleCount m_PeakTime;
+
+ CVProfNode *m_pParent;
+ CVProfNode *m_pChild;
+ CVProfNode *m_pSibling;
+
+ int m_BudgetGroupID;
+
+ int m_iClientData;
+ int m_iUniqueNodeID;
+};
+
+//-----------------------------------------------------------------------------
+//
+// Coordinator and root node of the profile hierarchy tree
+//
+
+enum VProfReportType_t
+{
+ VPRT_SUMMARY = ( 1 << 0 ),
+ VPRT_HIERARCHY = ( 1 << 1 ),
+ VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY = ( 1 << 2 ),
+ VPRT_LIST_BY_TIME = ( 1 << 3 ),
+ VPRT_LIST_BY_TIME_LESS_CHILDREN = ( 1 << 4 ),
+ VPRT_LIST_BY_AVG_TIME = ( 1 << 5 ),
+ VPRT_LIST_BY_AVG_TIME_LESS_CHILDREN = ( 1 << 6 ),
+ VPRT_LIST_BY_PEAK_TIME = ( 1 << 7 ),
+ VPRT_LIST_BY_PEAK_OVER_AVERAGE = ( 1 << 8 ),
+ VPRT_LIST_TOP_ITEMS_ONLY = ( 1 << 9 ),
+
+ VPRT_FULL = (0xffffffff & ~(VPRT_HIERARCHY_TIME_PER_FRAME_AND_COUNT_ONLY|VPRT_LIST_TOP_ITEMS_ONLY)),
+};
+
+enum CounterGroup_t
+{
+ COUNTER_GROUP_DEFAULT=0,
+ COUNTER_GROUP_NO_RESET, // The engine doesn't reset these counters. Usually, they are used
+ // like global variables that can be accessed across modules.
+ COUNTER_GROUP_TEXTURE_GLOBAL, // Global texture usage counters (totals for what is currently in memory).
+ COUNTER_GROUP_TEXTURE_PER_FRAME, // Per-frame texture usage counters.
+ COUNTER_GROUP_GRAPHICS_PER_FRAME, // Misc graphics counters that are reset each frame
+};
+
+class PLATFORM_CLASS CVProfile
+{
+public:
+ CVProfile();
+ ~CVProfile();
+
+ void Term();
+
+ //
+ // Runtime operations
+ //
+
+ void Start();
+ void Stop();
+
+ void SetTargetThreadId( unsigned id ) { m_TargetThreadId = id; }
+ unsigned GetTargetThreadId() { return m_TargetThreadId; }
+ bool InTargetThread() { return ( m_TargetThreadId == ThreadGetCurrentId() ); }
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+ enum VXConsoleReportMode_t
+ {
+ VXCONSOLE_REPORT_TIME = 0,
+ VXCONSOLE_REPORT_L2CACHE_MISSES,
+ VXCONSOLE_REPORT_LOAD_HIT_STORE,
+ VXCONSOLE_REPORT_COUNT,
+ };
+
+ void VXProfileStart();
+ void VXProfileUpdate();
+ void VXEnableUpdateMode( int event, bool bEnable );
+ void VXSendNodes( void );
+
+ void PMCDisableAllNodes(CVProfNode *pStartNode = NULL); ///< turn off l2 and lhs recording for everywhere
+ bool PMCEnableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
+ bool PMCDisableL2Upon(const tchar *pszNodeName, bool bRecursive = false); ///< enable l2 and lhs recording for one given node
+
+ void DumpEnabledPMCNodes( void );
+
+ void VXConsoleReportMode( VXConsoleReportMode_t mode );
+ void VXConsoleReportScale( VXConsoleReportMode_t mode, float flScale );
+#endif
+
+#ifdef _X360
+
+
+ // the CPU trace mode is actually a small state machine; it can be off, primed for
+ // single capture, primed for everything-in-a-frame capture, or currently in everything-in-a-frame
+ // capture.
+ enum CPUTraceState
+ {
+ kDisabled,
+ kFirstHitNode, // record from the first time we hit the node until that node ends
+ kAllNodesInFrame_WaitingForMark, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
+ kAllNodesInFrame_Recording, // we're recording all hits on a node this frame.
+
+ // Same as above, but going to record for > 1 frame
+ kAllNodesInFrame_WaitingForMarkMultiFrame, // we're going to record all the times a node is hit in a frame, but are waiting for the frame to start
+ kAllNodesInFrame_RecordingMultiFrame,
+ };
+
+ // Global switch to turn CPU tracing on or off at all. The idea is you set up a node first,
+ // then trigger tracing by throwing this to true. It'll reset back to false after the trace
+ // happens.
+ inline CPUTraceState GetCPUTraceMode();
+ inline void SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent = false, int nNumFrames = -1 );
+ inline void IncrementMultiTraceIndex(); // tick up the counter that gets appended to the multi-per-frame traces
+ inline unsigned int GetMultiTraceIndex(); // return the counter
+ void CPUTraceDisableAllNodes( CVProfNode *pStartNode = NULL ); // disable the cpu trace flag wherever it may be
+ CVProfNode *CPUTraceEnableForNode( const tchar *pszNodeName ); // enable cpu trace on this node only, disabling it wherever else it may be on.
+ CVProfNode *CPUTraceGetEnabledNode( CVProfNode *pStartNode = NULL ); // return the node enabled for CPU tracing, or NULL.
+ const char *GetCPUTraceFilename(); // get the filename the trace should write into.
+ const char *SetCPUTraceFilename( const char *filename ); // set the filename the trace should write into. (don't specify the extension; I'll do that.)
+ inline bool TraceCompleteEvent( void );
+
+#ifdef _X360
+ void LatchMultiFrame( int64 cycles );
+ void SpewWorstMultiFrame();
+#endif
+
+#endif
+
+ void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted );
+ void EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
+ void ExitScope();
+
+ void MarkFrame();
+ void ResetPeaks();
+
+ void Pause();
+ void Resume();
+ void Reset();
+
+ bool IsEnabled() const;
+ int GetDetailLevel() const;
+
+ bool AtRoot() const;
+
+ //
+ // Queries
+ //
+
+#ifdef VPROF_VTUNE_GROUP
+# define MAX_GROUP_STACK_DEPTH 1024
+
+ void EnableVTuneGroup( const tchar *pGroupName )
+ {
+ m_nVTuneGroupID = BudgetGroupNameToBudgetGroupID( pGroupName );
+ m_bVTuneGroupEnabled = true;
+ }
+ void DisableVTuneGroup( void )
+ {
+ m_bVTuneGroupEnabled = false;
+ }
+
+ inline void PushGroup( int nGroupID );
+ inline void PopGroup( void );
+#endif
+
+ int NumFramesSampled() { return m_nFrames; }
+ double GetPeakFrameTime();
+ double GetTotalTimeSampled();
+ double GetTimeLastFrame();
+
+ CVProfNode *GetRoot();
+ CVProfNode *FindNode( CVProfNode *pStartNode, const tchar *pszNode );
+ CVProfNode *GetCurrentNode();
+
+ void OutputReport( int type = VPRT_FULL, const tchar *pszStartNode = NULL, int budgetGroupID = -1 );
+
+ const tchar *GetBudgetGroupName( int budgetGroupID );
+ int GetBudgetGroupFlags( int budgetGroupID ) const; // Returns a combination of BUDGETFLAG_ defines.
+ int GetNumBudgetGroups( void );
+ void GetBudgetGroupColor( int budgetGroupID, int &r, int &g, int &b, int &a );
+ int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName );
+ int BudgetGroupNameToBudgetGroupID( const tchar *pBudgetGroupName, int budgetFlagsToORIn );
+ void RegisterNumBudgetGroupsChangedCallBack( void (*pCallBack)(void) );
+
+ int BudgetGroupNameToBudgetGroupIDNoCreate( const tchar *pBudgetGroupName ) { return FindBudgetGroupName( pBudgetGroupName ); }
+
+ void HideBudgetGroup( int budgetGroupID, bool bHide = true );
+ void HideBudgetGroup( const tchar *pszName, bool bHide = true ) { HideBudgetGroup( BudgetGroupNameToBudgetGroupID( pszName), bHide ); }
+
+ int *FindOrCreateCounter( const tchar *pName, CounterGroup_t eCounterGroup=COUNTER_GROUP_DEFAULT );
+ void ResetCounters( CounterGroup_t eCounterGroup );
+
+ int GetNumCounters( void ) const;
+
+ const tchar *GetCounterName( int index ) const;
+ int GetCounterValue( int index ) const;
+ const tchar *GetCounterNameAndValue( int index, int &val ) const;
+ CounterGroup_t GetCounterGroup( int index ) const;
+
+ // Performance monitoring events.
+ void PMEInitialized( bool bInit ) { m_bPMEInit = bInit; }
+ void PMEEnable( bool bEnable ) { m_bPMEEnabled = bEnable; }
+
+#ifdef _X360
+ bool UsePME( void ) { return ( CPMCData::IsInitialized() && m_bPMEEnabled ); }
+#elif defined( _PS3 )
+ inline bool UsePME( void ) { return false; }
+#else
+ bool UsePME( void ) { return ( m_bPMEInit && m_bPMEEnabled ); }
+#endif
+
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+
+protected:
+
+ void FreeNodes_R( CVProfNode *pNode );
+
+#ifdef VPROF_VTUNE_GROUP
+ bool VTuneGroupEnabled()
+ {
+ return m_bVTuneGroupEnabled;
+ }
+ int VTuneGroupID()
+ {
+ return m_nVTuneGroupID;
+ }
+#endif
+
+ void SumTimes( const tchar *pszStartNode, int budgetGroupID );
+ void SumTimes( CVProfNode *pNode, int budgetGroupID );
+ void DumpNodes( CVProfNode *pNode, int indent, bool bAverageAndCountOnly );
+ int FindBudgetGroupName( const tchar *pBudgetGroupName );
+ int AddBudgetGroupName( const tchar *pBudgetGroupName, int budgetFlags );
+
+#ifdef VPROF_VTUNE_GROUP
+ bool m_bVTuneGroupEnabled;
+ int m_nVTuneGroupID;
+ int m_GroupIDStack[MAX_GROUP_STACK_DEPTH];
+ int m_GroupIDStackDepth;
+#endif
+ int m_enabled;
+ bool m_fAtRoot; // tracked for efficiency of the "not profiling" case
+ CVProfNode *m_pCurNode;
+ CVProfNode m_Root;
+ int m_nFrames;
+ int m_ProfileDetailLevel;
+ int m_pausedEnabledDepth;
+
+ class CBudgetGroup
+ {
+ public:
+ tchar *m_pName;
+ int m_BudgetFlags;
+ };
+
+ CBudgetGroup *m_pBudgetGroups;
+ int m_nBudgetGroupNamesAllocated;
+ int m_nBudgetGroupNames;
+ void (*m_pNumBudgetGroupsChangedCallBack)(void);
+
+ // Performance monitoring events.
+ bool m_bPMEInit;
+ bool m_bPMEEnabled;
+
+ int m_Counters[MAXCOUNTERS];
+ char m_CounterGroups[MAXCOUNTERS]; // (These are CounterGroup_t's).
+ tchar *m_CounterNames[MAXCOUNTERS];
+ int m_NumCounters;
+
+#ifdef VPROF_VXCONSOLE_EXISTS
+ int m_UpdateMode;
+ int m_nFramesRemaining;
+ int m_nFrameCount;
+ int64 m_WorstCycles;
+ char m_WorstTraceFilename[128];
+ char m_CPUTraceFilename[128];
+ unsigned int m_iSuccessiveTraceIndex;
+ VXConsoleReportMode_t m_ReportMode;
+ float m_pReportScale[VXCONSOLE_REPORT_COUNT];
+ bool m_bTraceCompleteEvent;
+#endif
+#ifdef _X360
+ CPUTraceState m_iCPUTraceEnabled;
+#endif
+
+ unsigned m_TargetThreadId;
+};
+
+//-------------------------------------
+
+PLATFORM_INTERFACE CVProfile g_VProfCurrentProfile;
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE bool g_VProfSignalSpike;
+
+class CVProfSpikeDetector
+{
+public:
+ CVProfSpikeDetector( float spike ) :
+ m_timeLast( GetTimeLast() )
+ {
+ m_spike = spike;
+ m_Timer.Start();
+ }
+
+ ~CVProfSpikeDetector()
+ {
+ m_Timer.End();
+ if ( Plat_FloatTime() - m_timeLast > 2.0 )
+ {
+ m_timeLast = Plat_FloatTime();
+ if ( m_Timer.GetDuration().GetMillisecondsF() > m_spike )
+ {
+ g_VProfSignalSpike = true;
+ }
+ }
+ }
+
+private:
+ static float &GetTimeLast() { static float timeLast = 0; return timeLast; }
+ CFastTimer m_Timer;
+ float m_spike;
+ float &m_timeLast;
+};
+
+
+// Macro to signal a local spike. Meant as temporary instrumentation, do not leave in code
+#define VPROF_TEST_SPIKE( msec ) CVProfSpikeDetector UNIQUE_ID( msec )
+
+//-----------------------------------------------------------------------------
+
+#ifdef VPROF_VTUNE_GROUP
+inline void CVProfile::PushGroup( int nGroupID )
+{
+ // There is always at least one item on the stack since we force
+ // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
+ Assert( m_GroupIDStackDepth > 0 );
+ Assert( m_GroupIDStackDepth < MAX_GROUP_STACK_DEPTH );
+ m_GroupIDStack[m_GroupIDStackDepth] = nGroupID;
+ m_GroupIDStackDepth++;
+ if( m_GroupIDStack[m_GroupIDStackDepth-2] != nGroupID &&
+ VTuneGroupEnabled() &&
+ nGroupID == VTuneGroupID() )
+ {
+ vtune( true );
+ }
+}
+#endif // VPROF_VTUNE_GROUP
+
+#ifdef VPROF_VTUNE_GROUP
+inline void CVProfile::PopGroup( void )
+{
+ m_GroupIDStackDepth--;
+ // There is always at least one item on the stack since we force
+ // the first element to be VPROF_BUDGETGROUP_OTHER_UNACCOUNTED.
+ Assert( m_GroupIDStackDepth > 0 );
+ if( m_GroupIDStack[m_GroupIDStackDepth] != m_GroupIDStack[m_GroupIDStackDepth+1] &&
+ VTuneGroupEnabled() &&
+ m_GroupIDStack[m_GroupIDStackDepth+1] == VTuneGroupID() )
+ {
+ vtune( false );
+ }
+}
+#endif // VPROF_VTUNE_GROUP
+
+//-----------------------------------------------------------------------------
+
+
+class CVProfScope: public CVProfSnMarkerScope
+{
+public:
+ CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags );
+ ~CVProfScope();
+
+private:
+ bool m_bEnabled;
+};
+
+//-----------------------------------------------------------------------------
+//
+// CVProfNode, inline methods
+//
+
+inline CVProfNode::CVProfNode( const tchar * pszName, int detailLevel, CVProfNode *pParent, const tchar *pBudgetGroupName, int budgetFlags )
+ : m_pszName( pszName ),
+ m_nCurFrameCalls( 0 ),
+ m_nPrevFrameCalls( 0 ),
+ m_nRecursions( 0 ),
+ m_pParent( pParent ),
+ m_pChild( NULL ),
+ m_pSibling( NULL ),
+ m_iClientData( -1 )
+#ifdef _X360
+ , m_iBitFlags( 0 )
+#endif
+{
+ m_iUniqueNodeID = s_iCurrentUniqueNodeID++;
+
+ if ( m_iUniqueNodeID > 0 )
+ {
+ m_BudgetGroupID = g_VProfCurrentProfile.BudgetGroupNameToBudgetGroupID( pBudgetGroupName, budgetFlags );
+ }
+ else
+ {
+ m_BudgetGroupID = 0; // "m_Root" can't call BudgetGroupNameToBudgetGroupID because g_VProfCurrentProfile not yet initialized
+ }
+
+ Reset();
+
+ if( m_pParent && ( m_BudgetGroupID == VPROF_BUDGET_GROUP_ID_UNACCOUNTED ) )
+ {
+ m_BudgetGroupID = m_pParent->GetBudgetGroupID();
+ }
+}
+
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetParent()
+{
+ Assert( m_pParent );
+ return m_pParent;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetSibling()
+{
+ return m_pSibling;
+}
+
+//-------------------------------------
+// Hacky way to the previous sibling, only used from vprof panel at the moment,
+// so it didn't seem like it was worth the memory waste to add the reverse
+// link per node.
+
+inline CVProfNode *CVProfNode::GetPrevSibling()
+{
+ CVProfNode* p = GetParent();
+
+ if(!p)
+ return NULL;
+
+ CVProfNode* s;
+ for( s = p->GetChild();
+ s && ( s->GetSibling() != this );
+ s = s->GetSibling() )
+ ;
+
+ return s;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfNode::GetChild()
+{
+ return m_pChild;
+}
+
+//-------------------------------------
+
+inline const tchar *CVProfNode::GetName()
+{
+ return m_pszName;
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetTotalCalls()
+{
+ return m_nTotalCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetTotalTime()
+{
+ return m_TotalTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetCurCalls()
+{
+ return m_nCurFrameCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetCurTime()
+{
+ return m_CurFrameTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline int CVProfNode::GetPrevCalls()
+{
+ return m_nPrevFrameCalls;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetPrevTime()
+{
+ return m_PrevFrameTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetPeakTime()
+{
+ return m_PeakTime.GetMillisecondsF();
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetTotalTimeLessChildren()
+{
+ double result = GetTotalTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetTotalTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-------------------------------------
+
+inline double CVProfNode::GetCurTimeLessChildren()
+{
+ double result = GetCurTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetCurTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+inline double CVProfNode::GetPrevTimeLessChildren()
+{
+ double result = GetPrevTime();
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->GetPrevTime();
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetPrevL2CacheMissLessChildren()
+{
+ int result = m_iPrevL2CacheMiss;
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->m_iPrevL2CacheMiss;
+ pChild = pChild->GetSibling();
+ }
+ return result;
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetPrevLoadHitStoreLessChildren()
+{
+#ifndef _X360
+ return 0;
+#else
+ int result = m_iPrevLoadHitStores;
+ CVProfNode *pChild = GetChild();
+ while ( pChild )
+ {
+ result -= pChild->m_iPrevLoadHitStores;
+ pChild = pChild->GetSibling();
+ }
+ return result;
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+inline void CVProfNode::ClearPrevTime()
+{
+ m_PrevFrameTime.Init();
+}
+
+//-----------------------------------------------------------------------------
+inline int CVProfNode::GetL2CacheMisses( void )
+{
+#ifndef _X360
+ return m_L2Cache.GetL2CacheMisses();
+#else
+ return m_iTotalL2CacheMiss;
+#endif
+}
+
+#ifdef _X360
+inline int CVProfNode::GetLoadHitStores( void )
+{
+ return m_iTotalLoadHitStores;
+}
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// CVProfile, inline methods
+//
+
+//-------------------------------------
+
+inline bool CVProfile::IsEnabled() const
+{
+ return ( m_enabled != 0 );
+}
+
+//-------------------------------------
+
+inline int CVProfile::GetDetailLevel() const
+{
+ return m_ProfileDetailLevel;
+}
+
+
+//-------------------------------------
+
+inline bool CVProfile::AtRoot() const
+{
+ return m_fAtRoot;
+}
+
+//-------------------------------------
+
+inline void CVProfile::Start()
+{
+ if ( ++m_enabled == 1 )
+ {
+ m_Root.EnterScope();
+#ifdef VPROF_VXCONSOLE_EXISTS
+ VXProfileStart();
+#endif
+#ifdef _X360
+ CPMCData::InitializeOnceProgramWide();
+#endif
+ }
+}
+
+//-------------------------------------
+
+inline void CVProfile::Stop()
+{
+ if ( --m_enabled == 0 )
+ m_Root.ExitScope();
+}
+
+//-------------------------------------
+
+inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags )
+{
+ if ( ( m_enabled != 0 || !m_fAtRoot ) && InTargetThread() ) // if became disabled, need to unwind back to root before stopping
+ {
+ // Only account for vprof stuff on the primary thread.
+ //if( !Plat_IsPrimaryThread() )
+ // return;
+
+ if ( pszName != m_pCurNode->GetName() )
+ {
+ m_pCurNode = m_pCurNode->GetSubNode( pszName, detailLevel, pBudgetGroupName, budgetFlags );
+ }
+ m_pBudgetGroups[m_pCurNode->GetBudgetGroupID()].m_BudgetFlags |= budgetFlags;
+
+#if defined( _DEBUG ) && !defined( _X360 )
+ // 360 doesn't want this to allow tier0 debug/release .def files to match
+ if ( bAssertAccounted )
+ {
+ // FIXME
+ AssertOnce( m_pCurNode->GetBudgetGroupID() != 0 );
+ }
+#endif
+ m_pCurNode->EnterScope();
+ m_fAtRoot = false;
+ }
+#if defined(_X360) && defined(VPROF_PIX)
+ if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
+ PIXBeginNamedEvent( 0, pszName );
+#endif
+}
+
+inline void CVProfile::EnterScope( const tchar *pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted )
+{
+ EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, BUDGETFLAG_OTHER );
+}
+
+//-------------------------------------
+
+inline void CVProfile::ExitScope()
+{
+#if defined(_X360) && defined(VPROF_PIX)
+/*
+#ifdef PIXBeginNamedEvent
+#error
+#endif
+*/
+ if ( m_pCurNode->GetBudgetGroupID() != VPROF_BUDGET_GROUP_ID_UNACCOUNTED )
+ PIXEndNamedEvent();
+#endif
+ if ( ( !m_fAtRoot || m_enabled != 0 ) && InTargetThread() )
+ {
+ // Only account for vprof stuff on the primary thread.
+ //if( !Plat_IsPrimaryThread() )
+ // return;
+
+ // ExitScope will indicate whether we should back up to our parent (we may
+ // be profiling a recursive function)
+ if (m_pCurNode->ExitScope())
+ {
+ m_pCurNode = m_pCurNode->GetParent();
+ }
+ m_fAtRoot = ( m_pCurNode == &m_Root );
+ }
+}
+
+//-------------------------------------
+
+inline void CVProfile::Pause()
+{
+ m_pausedEnabledDepth = m_enabled;
+ m_enabled = 0;
+ if ( !AtRoot() )
+ m_Root.Pause();
+}
+
+//-------------------------------------
+
+inline void CVProfile::Resume()
+{
+ m_enabled = m_pausedEnabledDepth;
+ if ( !AtRoot() )
+ m_Root.Resume();
+}
+
+//-------------------------------------
+
+inline void CVProfile::Reset()
+{
+ m_Root.Reset();
+ m_nFrames = 0;
+}
+
+//-------------------------------------
+
+inline void CVProfile::ResetPeaks()
+{
+ m_Root.ResetPeak();
+}
+
+//-------------------------------------
+
+inline void CVProfile::MarkFrame()
+{
+ if ( m_enabled )
+ {
+ ++m_nFrames;
+ m_Root.ExitScope();
+ m_Root.MarkFrame();
+ m_Root.EnterScope();
+
+#ifdef _X360
+ // update the CPU trace state machine if enabled
+ switch ( GetCPUTraceMode() )
+ {
+ case kAllNodesInFrame_WaitingForMark:
+ // mark! Start recording a zillion traces.
+ m_iCPUTraceEnabled = kAllNodesInFrame_Recording;
+ break;
+ case kAllNodesInFrame_WaitingForMarkMultiFrame:
+ m_iCPUTraceEnabled = kAllNodesInFrame_RecordingMultiFrame;
+ break;
+ case kAllNodesInFrame_Recording:
+ // end of frame. stop recording if no more frames needed
+ m_iCPUTraceEnabled = kDisabled;
+ Msg("Frame ended. Recording no more CPU traces\n");
+
+ break;
+ case kAllNodesInFrame_RecordingMultiFrame:
+ // end of frame. stop recording if no more frames needed
+ if ( --m_nFramesRemaining == 0 )
+ {
+ m_iCPUTraceEnabled = kDisabled;
+ Msg("Frames ended. Recording no more CPU traces\n");
+
+ SpewWorstMultiFrame();
+ }
+
+ ++m_nFrameCount;
+
+ break;
+ default:
+ // no default
+ break;
+ }
+#endif
+ }
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetTotalTimeSampled()
+{
+ return m_Root.GetTotalTime();
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetPeakFrameTime()
+{
+ return m_Root.GetPeakTime();
+}
+
+//-------------------------------------
+
+inline double CVProfile::GetTimeLastFrame()
+{
+ return m_Root.GetCurTime();
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfile::GetRoot()
+{
+ return &m_Root;
+}
+
+//-------------------------------------
+
+inline CVProfNode *CVProfile::GetCurrentNode()
+{
+ return m_pCurNode;
+}
+
+
+inline const tchar *CVProfile::GetBudgetGroupName( int budgetGroupID )
+{
+ Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
+ return m_pBudgetGroups[budgetGroupID].m_pName;
+}
+
+inline int CVProfile::GetBudgetGroupFlags( int budgetGroupID ) const
+{
+ Assert( budgetGroupID >= 0 && budgetGroupID < m_nBudgetGroupNames );
+ return m_pBudgetGroups[budgetGroupID].m_BudgetFlags;
+}
+
+#ifdef _X360
+
+inline CVProfile::CPUTraceState CVProfile::GetCPUTraceMode()
+{
+ return m_iCPUTraceEnabled;
+}
+
+inline void CVProfile::SetCPUTraceEnabled( CPUTraceState enabled, bool bTraceCompleteEvent /*=true*/, int nNumFrames /*= -1*/ )
+{
+ m_iCPUTraceEnabled = enabled;
+ m_bTraceCompleteEvent = bTraceCompleteEvent;
+ if ( nNumFrames != -1 )
+ {
+ m_nFramesRemaining = nNumFrames;
+ m_nFrameCount = 0;
+ m_WorstCycles = 0;
+ m_WorstTraceFilename[ 0 ] = 0;
+ }
+}
+
+inline void CVProfile::IncrementMultiTraceIndex()
+{
+ ++m_iSuccessiveTraceIndex;
+}
+
+inline unsigned int CVProfile::GetMultiTraceIndex()
+{
+ return m_iSuccessiveTraceIndex;
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+
+inline CVProfScope::CVProfScope( const tchar * pszName, int detailLevel, const tchar *pBudgetGroupName, bool bAssertAccounted, int budgetFlags ):
+ CVProfSnMarkerScope( pszName ),
+ m_bEnabled( g_VProfCurrentProfile.IsEnabled() )
+{
+ if ( m_bEnabled )
+ {
+ g_VProfCurrentProfile.EnterScope( pszName, detailLevel, pBudgetGroupName, bAssertAccounted, budgetFlags );
+ }
+}
+
+//-------------------------------------
+
+inline CVProfScope::~CVProfScope()
+{
+ if ( m_bEnabled )
+ {
+ g_VProfCurrentProfile.ExitScope();
+ }
+}
+
+class CVProfCounter
+{
+public:
+ CVProfCounter( const tchar *pName, CounterGroup_t group=COUNTER_GROUP_DEFAULT )
+ {
+ m_pCounter = g_VProfCurrentProfile.FindOrCreateCounter( pName, group );
+ Assert( m_pCounter );
+ }
+ ~CVProfCounter()
+ {
+ }
+ void Increment( int val )
+ {
+ Assert( m_pCounter );
+ *m_pCounter += val;
+ }
+ void Set( int val )
+ {
+ Assert( m_pCounter );
+ *m_pCounter = val;
+ }
+private:
+ int *m_pCounter;
+};
+
+#endif
+
+#ifdef _X360
+
+#include "xbox/xbox_console.h"
+#include "tracerecording.h"
+#include "tier1/fmtstr.h"
+#pragma comment( lib, "tracerecording.lib" )
+#pragma comment( lib, "xbdm.lib" )
+
+class CPIXRecorder
+{
+public:
+ CPIXRecorder() : m_bActive( false ) {}
+ ~CPIXRecorder() { Stop(); }
+
+ void Start( const char *pszFilename = "capture" )
+ {
+ if ( !m_bActive )
+ {
+ if ( !XTraceStartRecording( CFmtStr( "e:\\%s.pix2", pszFilename ) ) )
+ {
+ Msg( "XTraceStartRecording failed, error code %d\n", GetLastError() );
+ }
+ else
+ {
+ m_bActive = true;
+ }
+ }
+ }
+
+ void Stop()
+ {
+ if ( m_bActive )
+ {
+ m_bActive = false;
+ if ( XTraceStopRecording() )
+ {
+ Msg( "CPU trace finished.\n" );
+ // signal VXConsole that trace is completed
+ XBX_rTraceComplete();
+ }
+ }
+ }
+
+private:
+ bool m_bActive;
+};
+
+#define VPROF_BEGIN_PIX_BLOCK( convar ) \
+ { \
+ bool bRunPix = 0; \
+ static CFastTimer PIXTimer; \
+ extern ConVar convar; \
+ ConVar &PIXConvar = convar; \
+ CPIXRecorder PIXRecorder; \
+ { \
+ PIXLabel: \
+ if ( bRunPix ) \
+ { \
+ PIXRecorder.Start(); \
+ } \
+ else \
+ { \
+ if ( PIXConvar.GetBool() ) \
+ { \
+ PIXTimer.Start(); \
+ } \
+ } \
+ {
+
+
+#define VPROF_END_PIX_BLOCK() \
+ } \
+ \
+ if ( !bRunPix ) \
+ { \
+ if ( PIXConvar.GetBool() ) \
+ { \
+ PIXTimer.End(); \
+ if ( PIXTimer.GetDuration().GetMillisecondsF() > PIXConvar.GetFloat() ) \
+ { \
+ PIXConvar.SetValue( 0 ); \
+ bRunPix = true; \
+ goto PIXLabel; \
+ } \
+ } \
+ } \
+ else \
+ { \
+ PIXRecorder.Stop(); \
+ } \
+ } \
+ }
+#else
+#define VPROF_BEGIN_PIX_BLOCK( PIXConvar ) {
+#define VPROF_END_PIX_BLOCK() }
+#endif
+
+
+#ifdef VPROF_UNDO_PIX
+#undef USE_PIX
+#undef _PIX_H_
+#undef PIXBeginNamedEvent
+#undef PIXEndNamedEvent
+#undef PIXSetMarker
+#undef PIXNameThread
+#include <pix.h>
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
+
+#endif
+
+//=============================================================================
diff --git a/external/vpc/public/tier0/vprof_sn.h b/external/vpc/public/tier0/vprof_sn.h
new file mode 100644
index 0000000..ecf776f
--- /dev/null
+++ b/external/vpc/public/tier0/vprof_sn.h
@@ -0,0 +1,31 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+#ifndef TIER_V0PROF_SN_HDR
+#define TIER_V0PROF_SN_HDR
+
+// enable this to get detailed SN Tuner markers. PS3 specific
+#if defined( SN_TARGET_PS3 ) && !defined(_CERT)
+#define VPROF_SN_LEVEL 0
+
+extern "C" void(*g_pfnPushMarker)( const char * pName );
+extern "C" void(*g_pfnPopMarker)();
+
+class CVProfSnMarkerScope
+{
+public:
+ CVProfSnMarkerScope( const char * pszName )
+ {
+ g_pfnPushMarker( pszName );
+ }
+ ~CVProfSnMarkerScope()
+ {
+ g_pfnPopMarker( );
+ }
+};
+
+#else
+
+class CVProfSnMarkerScope { public: CVProfSnMarkerScope( const char * ) {} };
+
+#endif
+
+#endif \ No newline at end of file
diff --git a/external/vpc/public/tier0/wchartypes.h b/external/vpc/public/tier0/wchartypes.h
new file mode 100644
index 0000000..8446b68
--- /dev/null
+++ b/external/vpc/public/tier0/wchartypes.h
@@ -0,0 +1,101 @@
+//========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose: All of our code is completely Unicode. Instead of char, you should
+// use wchar, uint8, or char8, as explained below.
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#ifndef WCHARTYPES_H
+#define WCHARTYPES_H
+#ifdef _WIN32
+#pragma once
+#endif
+#include "stddef.h"
+#ifdef _INC_TCHAR
+#error ("Must include tier0 type headers before tchar.h")
+#endif
+
+// Temporarily turn off Valve defines
+#include "tier0/valve_off.h"
+
+#if !defined(_WCHAR_T_DEFINED) && !defined( __WCHAR_TYPE__ ) && !defined(GNUC)
+typedef unsigned short wchar_t;
+#define _WCHAR_T_DEFINED
+#endif
+
+// char8
+// char8 is equivalent to char, and should be used when you really need a char
+// (for example, when calling an external function that's declared to take
+// chars).
+typedef char char8;
+
+// uint8
+// uint8 is equivalent to byte (but is preferred over byte for clarity). Use this
+// whenever you mean a byte (for example, one byte of a network packet).
+// uint8 itself is defined in platform.h
+typedef unsigned char BYTE;
+typedef unsigned char byte;
+
+// wchar
+// wchar is a single character of text (currently 16 bits, as all of our text is
+// Unicode). Use this whenever you mean a piece of text (for example, in a string).
+typedef wchar_t wchar;
+//typedef char wchar;
+
+// __WFILE__
+// This is a Unicode version of __FILE__
+#define WIDEN2(x) L ## x
+#define WIDEN(x) WIDEN2(x)
+#define __WFILE__ WIDEN(__FILE__)
+
+#ifdef STEAM
+#ifndef _UNICODE
+#define FORCED_UNICODE
+#endif
+#define _UNICODE
+#endif
+
+#if defined( POSIX ) || defined( _PS3 )
+#define _tcsstr strstr
+#define _tcsicmp stricmp
+#define _tcscmp strcmp
+#define _tcscpy strcpy
+#define _tcsncpy strncpy
+#define _tcsrchr strrchr
+#define _tcslen strlen
+#define _tfopen fopen
+#define _stprintf sprintf
+#define _ftprintf fprintf
+#define _vsntprintf _vsnprintf
+#define _tprintf printf
+#define _sntprintf _snprintf
+#define _T(s) s
+#else
+#include <tchar.h>
+#endif
+
+#if defined(_UNICODE)
+typedef wchar tchar;
+#define tstring wstring
+#define __TFILE__ __WFILE__
+#define TCHAR_IS_WCHAR
+#else
+typedef char tchar;
+#define tstring string
+#define __TFILE__ __FILE__
+#define TCHAR_IS_CHAR
+#endif
+
+#ifdef FORCED_UNICODE
+#undef _UNICODE
+#endif
+
+// Turn valve defines back on
+#include "tier0/valve_on.h"
+
+
+#endif // WCHARTYPES
+
+
diff --git a/external/vpc/public/tier0/win32consoleio.h b/external/vpc/public/tier0/win32consoleio.h
new file mode 100644
index 0000000..92b3914
--- /dev/null
+++ b/external/vpc/public/tier0/win32consoleio.h
@@ -0,0 +1,32 @@
+//======= Copyright � 1996-2006, Valve Corporation, All rights reserved. ======
+//
+// Purpose: Win32 Console API helpers
+//
+//=============================================================================
+#ifndef WIN32_CONSOLE_IO_H
+#define WIN32_CONSOLE_IO_H
+
+#if defined( COMPILER_MSVC )
+#pragma once
+#endif
+
+// Function to attach a console for I/O to a Win32 GUI application in a reasonably smart fashion.
+PLATFORM_INTERFACE bool SetupWin32ConsoleIO();
+
+// Win32 Console Color API Helpers, originally from cmdlib.
+
+struct Win32ConsoleColorContext_t
+{
+ int m_InitialColor;
+ uint16 m_LastColor;
+ uint16 m_BadColor;
+ uint16 m_BackgroundFlags;
+};
+
+PLATFORM_INTERFACE void InitWin32ConsoleColorContext( Win32ConsoleColorContext_t *pContext );
+
+PLATFORM_INTERFACE uint16 SetWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, int nRed, int nGreen, int nBlue, int nIntensity );
+
+PLATFORM_INTERFACE void RestoreWin32ConsoleColor( Win32ConsoleColorContext_t *pContext, uint16 prevColor );
+
+#endif
diff --git a/external/vpc/public/tier0/xbox_codeline_defines.h b/external/vpc/public/tier0/xbox_codeline_defines.h
new file mode 100644
index 0000000..3f7b544
--- /dev/null
+++ b/external/vpc/public/tier0/xbox_codeline_defines.h
@@ -0,0 +1,16 @@
+//========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef XBOX_CODELINE_DEFINES_H
+#define XBOX_CODELINE_DEFINES_H
+
+
+// In the regular src_main codeline, we leave this out.
+//#define IN_XBOX_CODELINE
+
+
+#endif // XBOX_CODELINE_DEFINES_H