summaryrefslogtreecommitdiff
path: root/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 /public/tier0
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'public/tier0')
-rw-r--r--public/tier0/EventMasks.h480
-rw-r--r--public/tier0/EventModes.h1787
-rw-r--r--public/tier0/IOCTLCodes.h29
-rw-r--r--public/tier0/K8PerformanceCounters.h2032
-rw-r--r--public/tier0/P4PerformanceCounters.h322
-rw-r--r--public/tier0/P5P6PerformanceCounters.h225
-rw-r--r--public/tier0/PMELib.h192
-rw-r--r--public/tier0/afxmem_override.cpp456
-rw-r--r--public/tier0/annotations.h84
-rw-r--r--public/tier0/basetypes.h398
-rw-r--r--public/tier0/commonmacros.h174
-rw-r--r--public/tier0/cpumonitoring.h33
-rw-r--r--public/tier0/dbg.h820
-rw-r--r--public/tier0/dbgflag.h65
-rw-r--r--public/tier0/dynfunction.h136
-rw-r--r--public/tier0/etwprof.h157
-rw-r--r--public/tier0/fasttimer.h569
-rw-r--r--public/tier0/ia32detect.h377
-rw-r--r--public/tier0/icommandline.h61
-rw-r--r--public/tier0/l2cache.h46
-rw-r--r--public/tier0/mem.h47
-rw-r--r--public/tier0/memalloc.h661
-rw-r--r--public/tier0/memdbgoff.h25
-rw-r--r--public/tier0/memdbgon.h318
-rw-r--r--public/tier0/memoverride.cpp1462
-rw-r--r--public/tier0/minidump.h104
-rw-r--r--public/tier0/platform.h1691
-rw-r--r--public/tier0/pmc360.h73
-rw-r--r--public/tier0/pointeroverride.asm17
-rw-r--r--public/tier0/progressbar.h23
-rw-r--r--public/tier0/protected_things.h271
-rw-r--r--public/tier0/stacktools.h153
-rw-r--r--public/tier0/systeminformation.h56
-rw-r--r--public/tier0/testthread.h60
-rw-r--r--public/tier0/threadtools.h1825
-rw-r--r--public/tier0/tmapi_dummy.h84
-rw-r--r--public/tier0/tslist.h1004
-rw-r--r--public/tier0/type_traits.h32
-rw-r--r--public/tier0/validator.h73
-rw-r--r--public/tier0/valobject.h72
-rw-r--r--public/tier0/valve_minmax_off.h7
-rw-r--r--public/tier0/valve_minmax_on.h9
-rw-r--r--public/tier0/valve_off.h30
-rw-r--r--public/tier0/valve_on.h31
-rw-r--r--public/tier0/vcr_shared.h54
-rw-r--r--public/tier0/vcrmode.h306
-rw-r--r--public/tier0/vprof.h1440
-rw-r--r--public/tier0/vprof_telemetry.h154
-rw-r--r--public/tier0/wchartypes.h109
-rw-r--r--public/tier0/xbox_codeline_defines.h16
50 files changed, 18650 insertions, 0 deletions
diff --git a/public/tier0/EventMasks.h b/public/tier0/EventMasks.h
new file mode 100644
index 0000000..0185567
--- /dev/null
+++ b/public/tier0/EventMasks.h
@@ -0,0 +1,480 @@
+//========= Copyright 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/public/tier0/EventModes.h b/public/tier0/EventModes.h
new file mode 100644
index 0000000..b6b9756
--- /dev/null
+++ b/public/tier0/EventModes.h
@@ -0,0 +1,1787 @@
+//========= Copyright 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/public/tier0/IOCTLCodes.h b/public/tier0/IOCTLCodes.h
new file mode 100644
index 0000000..a8f50d0
--- /dev/null
+++ b/public/tier0/IOCTLCodes.h
@@ -0,0 +1,29 @@
+//========= Copyright 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/public/tier0/K8PerformanceCounters.h b/public/tier0/K8PerformanceCounters.h
new file mode 100644
index 0000000..4367dff
--- /dev/null
+++ b/public/tier0/K8PerformanceCounters.h
@@ -0,0 +1,2032 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef K8PERFORMANCECOUNTERS_H
+#define K8PERFORMANCECOUNTERS_H
+
+/*
+ * AMD K8 events.
+ *
+ */
+
+
+
+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/public/tier0/P4PerformanceCounters.h b/public/tier0/P4PerformanceCounters.h
new file mode 100644
index 0000000..b52b691
--- /dev/null
+++ b/public/tier0/P4PerformanceCounters.h
@@ -0,0 +1,322 @@
+//========= Copyright 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/public/tier0/P5P6PerformanceCounters.h b/public/tier0/P5P6PerformanceCounters.h
new file mode 100644
index 0000000..a765756
--- /dev/null
+++ b/public/tier0/P5P6PerformanceCounters.h
@@ -0,0 +1,225 @@
+//========= Copyright 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/public/tier0/PMELib.h b/public/tier0/PMELib.h
new file mode 100644
index 0000000..5eeb63c
--- /dev/null
+++ b/public/tier0/PMELib.h
@@ -0,0 +1,192 @@
+//========= Copyright 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
+#define RDTSC(var) var = __rdtsc()
+
+// RDPMC Instruction macro
+#define RDPMC(counter, var) \
+_asm mov ecx, counter \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+
+// RDPMC Instruction macro, for performance counter 1 (ecx = 1)
+#define RDPMC0(var) \
+_asm mov ecx, 0 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+
+#define RDPMC1(var) \
+_asm mov ecx, 1 \
+_asm RDPMC \
+_asm mov DWORD PTR var,eax \
+_asm mov DWORD PTR var+4,edx
+
+#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/public/tier0/afxmem_override.cpp b/public/tier0/afxmem_override.cpp
new file mode 100644
index 0000000..f5794b2
--- /dev/null
+++ b/public/tier0/afxmem_override.cpp
@@ -0,0 +1,456 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+// File extracted from MFC due to symbol conflicts
+
+// This is a part of the Microsoft Foundation Classes C++ library.
+// Copyright (C) Microsoft Corporation
+// All rights reserved.
+//
+// This source code is only intended as a supplement to the
+// Microsoft Foundation Classes Reference and related
+// electronic documentation provided with the library.
+// See these sources for detailed information regarding the
+// Microsoft Foundation Classes product.
+
+#include "stdafx.h"
+
+#ifdef AFX_CORE1_SEG
+#pragma code_seg(AFX_CORE1_SEG)
+#endif
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Debug memory globals and implementation helpers
+
+#ifdef _DEBUG // most of this file is for debugging
+
+void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine);
+#if _MSC_VER >= 1210
+void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine);
+#endif
+
+/////////////////////////////////////////////////////////////////////////////
+// test allocation routines
+
+void* PASCAL CObject::operator new(size_t nSize)
+{
+#ifdef _AFX_NO_DEBUG_CRT
+ return ::operator new(nSize);
+#else
+ return ::operator new(nSize, _AFX_CLIENT_BLOCK, NULL, 0);
+#endif // _AFX_NO_DEBUG_CRT
+}
+
+void PASCAL CObject::operator delete(void* p)
+{
+#ifdef _AFX_NO_DEBUG_CRT
+ free(p);
+#else
+ _free_dbg(p, _AFX_CLIENT_BLOCK);
+#endif
+}
+
+#if _MSC_VER >= 1200
+void PASCAL CObject::operator delete(void* p, void*)
+{
+#ifdef _AFX_NO_DEBUG_CRT
+ free(p);
+#else
+ _free_dbg(p, _AFX_CLIENT_BLOCK);
+#endif
+}
+#endif
+
+#ifndef _AFX_NO_DEBUG_CRT
+
+void* __cdecl operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
+{
+ return ::operator new(nSize, _NORMAL_BLOCK, lpszFileName, nLine);
+}
+
+#if _MSC_VER >= 1210
+void* __cdecl operator new[](size_t nSize, LPCSTR lpszFileName, int nLine)
+{
+ return ::operator new[](nSize, _NORMAL_BLOCK, lpszFileName, nLine);
+}
+#endif
+
+#if _MSC_VER >= 1200
+void __cdecl operator delete(void* pData, LPCSTR /* lpszFileName */,
+ int /* nLine */)
+{
+ ::operator delete(pData);
+}
+#endif
+
+#if _MSC_VER >= 1210
+void __cdecl operator delete[](void* pData, LPCSTR /* lpszFileName */,
+ int /* nLine */)
+{
+ ::operator delete(pData);
+}
+#endif
+
+void* PASCAL
+CObject::operator new(size_t nSize, LPCSTR lpszFileName, int nLine)
+{
+ return ::operator new(nSize, _AFX_CLIENT_BLOCK, lpszFileName, nLine);
+}
+
+#if _MSC_VER >= 1200
+void PASCAL
+CObject::operator delete(void *pObject, LPCSTR /* lpszFileName */,
+ int /* nLine */)
+{
+#ifdef _AFX_NO_DEBUG_CRT
+ free(pObject);
+#else
+ _free_dbg(pObject, _AFX_CLIENT_BLOCK);
+#endif
+}
+#endif
+
+void* AFXAPI AfxAllocMemoryDebug(size_t nSize, BOOL bIsObject, LPCSTR lpszFileName, int nLine)
+{
+ return _malloc_dbg(nSize, bIsObject ? _AFX_CLIENT_BLOCK : _NORMAL_BLOCK,
+ lpszFileName, nLine);
+}
+
+void AFXAPI AfxFreeMemoryDebug(void* pbData, BOOL bIsObject)
+{
+ _free_dbg(pbData, bIsObject ? _AFX_CLIENT_BLOCK : _NORMAL_BLOCK);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// allocation failure hook, tracking turn on
+
+BOOL AFXAPI _AfxDefaultAllocHook(size_t, BOOL, LONG)
+ { return TRUE; }
+
+AFX_STATIC_DATA AFX_ALLOC_HOOK pfnAllocHook = _AfxDefaultAllocHook;
+
+AFX_STATIC_DATA _CRT_ALLOC_HOOK pfnCrtAllocHook = NULL;
+#if _MSC_VER >= 1200
+int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
+ int nBlockUse, long lRequest, const unsigned char * szFilename, int nLine)
+#else
+int __cdecl _AfxAllocHookProxy(int nAllocType, void * pvData, size_t nSize,
+ int nBlockUse, long lRequest, const char * szFilename, int nLine)
+#endif
+{
+#if _MSC_VER >= 1200
+ if (nAllocType != _HOOK_ALLOC)
+ return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
+ nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
+ if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _AFX_CLIENT_BLOCK, lRequest))
+ return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
+ nBlockUse, lRequest, (const unsigned char*) szFilename, nLine);
+#else
+ if (nAllocType != _HOOK_ALLOC)
+ return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
+ nBlockUse, lRequest, szFilename, nLine);
+ if ((pfnAllocHook)(nSize, _BLOCK_TYPE(nBlockUse) == _AFX_CLIENT_BLOCK, lRequest))
+ return (pfnCrtAllocHook)(nAllocType, pvData, nSize,
+ nBlockUse, lRequest, szFilename, nLine);
+#endif
+ return FALSE;
+}
+
+AFX_ALLOC_HOOK AFXAPI AfxSetAllocHook(AFX_ALLOC_HOOK pfnNewHook)
+{
+ if (pfnCrtAllocHook == NULL)
+ pfnCrtAllocHook = _CrtSetAllocHook(_AfxAllocHookProxy);
+
+ AFX_ALLOC_HOOK pfnOldHook = pfnAllocHook;
+ pfnAllocHook = pfnNewHook;
+ return pfnOldHook;
+}
+
+// This can be set to TRUE to override all AfxEnableMemoryTracking calls,
+// allowing all allocations, even MFC internal allocations to be tracked.
+BOOL _afxMemoryLeakOverride = FALSE;
+
+BOOL AFXAPI AfxEnableMemoryTracking(BOOL bTrack)
+{
+ if (_afxMemoryLeakOverride)
+ return TRUE;
+
+ int nOldState = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
+ if (bTrack)
+ _CrtSetDbgFlag(nOldState | _CRTDBG_ALLOC_MEM_DF);
+ else
+ _CrtSetDbgFlag(nOldState & ~_CRTDBG_ALLOC_MEM_DF);
+ return nOldState & _CRTDBG_ALLOC_MEM_DF;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// stop on a specific memory request
+
+// Obsolete API
+void AFXAPI AfxSetAllocStop(LONG lRequestNumber)
+{
+ _CrtSetBreakAlloc(lRequestNumber);
+}
+
+BOOL AFXAPI AfxCheckMemory()
+ // check all of memory (look for memory tromps)
+{
+ return _CrtCheckMemory();
+}
+
+// -- true if block of exact size, allocated on the heap
+// -- set *plRequestNumber to request number (or 0)
+BOOL AFXAPI AfxIsMemoryBlock(const void* pData, UINT nBytes,
+ LONG* plRequestNumber)
+{
+ return _CrtIsMemoryBlock(pData, nBytes, plRequestNumber, NULL, NULL);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// CMemoryState
+
+CMemoryState::CMemoryState()
+{
+ memset(this, 0, sizeof(*this));
+}
+
+void CMemoryState::UpdateData()
+{
+ for(int i = 0; i < nBlockUseMax; i++)
+ {
+ m_lCounts[i] = m_memState.lCounts[i];
+ m_lSizes[i] = m_memState.lSizes[i];
+ }
+ m_lHighWaterCount = m_memState.lHighWaterCount;
+ m_lTotalCount = m_memState.lTotalCount;
+}
+
+// fills 'this' with the difference, returns TRUE if significant
+BOOL CMemoryState::Difference(const CMemoryState& oldState,
+ const CMemoryState& newState)
+{
+ int nResult = _CrtMemDifference(&m_memState, &oldState.m_memState, &newState.m_memState);
+ UpdateData();
+ return nResult != 0;
+}
+
+void CMemoryState::DumpStatistics() const
+{
+ _CrtMemDumpStatistics(&m_memState);
+}
+
+// -- fill with current memory state
+void CMemoryState::Checkpoint()
+{
+ _CrtMemCheckpoint(&m_memState);
+ UpdateData();
+}
+
+// Dump objects created after this memory state was checkpointed
+// Will dump all objects if this memory state wasn't checkpointed
+// Dump all objects, report about non-objects also
+// List request number in {}
+void CMemoryState::DumpAllObjectsSince() const
+{
+ _CrtMemDumpAllObjectsSince(&m_memState);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Enumerate all objects allocated in the diagnostic memory heap
+
+struct _AFX_ENUM_CONTEXT
+{
+ void (*m_pfn)(CObject*,void*);
+ void* m_pContext;
+};
+
+AFX_STATIC void _AfxDoForAllObjectsProxy(void* pObject, void* pContext)
+{
+ _AFX_ENUM_CONTEXT* p = (_AFX_ENUM_CONTEXT*)pContext;
+ (*p->m_pfn)((CObject*)pObject, p->m_pContext);
+}
+
+void AFXAPI
+AfxDoForAllObjects(void (AFX_CDECL *pfn)(CObject*, void*), void* pContext)
+{
+ if (pfn == NULL)
+ {
+ AfxThrowInvalidArgException();
+ }
+ _AFX_ENUM_CONTEXT context;
+ context.m_pfn = pfn;
+ context.m_pContext = pContext;
+ _CrtDoForAllClientObjects(_AfxDoForAllObjectsProxy, &context);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+// Automatic debug memory diagnostics
+
+BOOL AFXAPI AfxDumpMemoryLeaks()
+{
+ return _CrtDumpMemoryLeaks();
+}
+
+#endif // _AFX_NO_DEBUG_CRT
+#endif // _DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
+// Non-diagnostic memory routines
+
+int AFX_CDECL AfxNewHandler(size_t /* nSize */)
+{
+ AfxThrowMemoryException();
+}
+
+#pragma warning(disable: 4273)
+
+#ifndef _AFXDLL
+_PNH _afxNewHandler = &AfxNewHandler;
+#endif
+
+_PNH AFXAPI AfxGetNewHandler(void)
+{
+#ifdef _AFXDLL
+ AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
+ return pState->m_pfnNewHandler;
+#else
+ return _afxNewHandler;
+#endif
+}
+
+_PNH AFXAPI AfxSetNewHandler(_PNH pfnNewHandler)
+{
+#ifdef _AFXDLL
+ AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
+ _PNH pfnOldHandler = pState->m_pfnNewHandler;
+ pState->m_pfnNewHandler = pfnNewHandler;
+ return pfnOldHandler;
+#else
+ _PNH pfnOldHandler = _afxNewHandler;
+ _afxNewHandler = pfnNewHandler;
+ return pfnOldHandler;
+#endif
+}
+
+AFX_STATIC_DATA const _PNH _pfnUninitialized = (_PNH)-1;
+
+void* __cdecl operator new(size_t nSize)
+{
+ void* pResult;
+#ifdef _AFXDLL
+ _PNH pfnNewHandler = _pfnUninitialized;
+#endif
+ for (;;)
+ {
+#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
+ pResult = _malloc_dbg(nSize, _NORMAL_BLOCK, NULL, 0);
+#else
+ pResult = malloc(nSize);
+#endif
+ if (pResult != NULL)
+ return pResult;
+
+#ifdef _AFXDLL
+ if (pfnNewHandler == _pfnUninitialized)
+ {
+ AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
+ pfnNewHandler = pState->m_pfnNewHandler;
+ }
+ if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
+ break;
+#else
+ if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
+ break;
+#endif
+ }
+ return pResult;
+}
+
+void __cdecl operator delete(void* p)
+{
+#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
+ _free_dbg(p, _NORMAL_BLOCK);
+#else
+ free(p);
+#endif
+}
+
+#if _MSC_VER >= 1210
+void* __cdecl operator new[](size_t nSize)
+{
+ return ::operator new(nSize);
+}
+
+void __cdecl operator delete[](void* p)
+{
+ ::operator delete(p);
+}
+#endif
+
+#ifdef _DEBUG
+
+void* __cdecl operator new(size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
+{
+#ifdef _AFX_NO_DEBUG_CRT
+ UNUSED_ALWAYS(nType);
+ UNUSED_ALWAYS(lpszFileName);
+ UNUSED_ALWAYS(nLine);
+ return ::operator new(nSize);
+#else
+ void* pResult;
+#ifdef _AFXDLL
+ _PNH pfnNewHandler = _pfnUninitialized;
+#endif
+ for (;;)
+ {
+ pResult = _malloc_dbg(nSize, nType, lpszFileName, nLine);
+ if (pResult != NULL)
+ return pResult;
+
+#ifdef _AFXDLL
+ if (pfnNewHandler == _pfnUninitialized)
+ {
+ AFX_MODULE_THREAD_STATE* pState = AfxGetModuleThreadState();
+ pfnNewHandler = pState->m_pfnNewHandler;
+ }
+ if (pfnNewHandler == NULL || (*pfnNewHandler)(nSize) == 0)
+ break;
+#else
+ if (_afxNewHandler == NULL || (*_afxNewHandler)(nSize) == 0)
+ break;
+#endif
+ }
+ return pResult;
+#endif
+}
+
+#if _MSC_VER >= 1700
+void __cdecl operator delete(void* p, int nType, LPCSTR /* lpszFileName */, int /* nLine */)
+{
+#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
+ _free_dbg(p, nType);
+#else
+ free(p);
+#endif
+}
+#endif // _MSC_VER >= 1200
+
+#if _MSC_VER >= 1700
+void* __cdecl operator new[](size_t nSize, int nType, LPCSTR lpszFileName, int nLine)
+{
+ return ::operator new(nSize, nType, lpszFileName, nLine);
+}
+void __cdecl operator delete[](void* p, int nType, LPCSTR lpszFileName, int nLine)
+{
+ ::operator delete(p, nType, lpszFileName, nLine);
+}
+#endif // _MSC_VER >= 1210
+
+#endif //_DEBUG
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/public/tier0/annotations.h b/public/tier0/annotations.h
new file mode 100644
index 0000000..7e0f469
--- /dev/null
+++ b/public/tier0/annotations.h
@@ -0,0 +1,84 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#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>
+
+// 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_CAP_C(x) _Out_cap_c_(x) // Output buffer with specified *constant* capacity in elements
+#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
+// Used for annotating functions to describe their return types.
+#define MUST_CHECK_RETURN _Check_return_
+// 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_CAP_C(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
+#define MUST_CHECK_RETURN
+#endif
+
+#endif // ANALYSIS_ANNOTATIONS_H
diff --git a/public/tier0/basetypes.h b/public/tier0/basetypes.h
new file mode 100644
index 0000000..22ce51b
--- /dev/null
+++ b/public/tier0/basetypes.h
@@ -0,0 +1,398 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef BASETYPES_H
+#define BASETYPES_H
+
+#include "commonmacros.h"
+#include "wchartypes.h"
+
+#include "tier0/valve_off.h"
+
+#ifdef _WIN32
+#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 )
+
+
+#include "protected_things.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"
+
+#ifdef IN_XBOX_CODELINE
+#define XBOX_CODELINE_ONLY()
+#else
+#define XBOX_CODELINE_ONLY() Error_Compiling_Code_Only_Valid_in_Xbox_Codeline
+#endif
+
+// stdio.h
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#ifdef POSIX
+#include <stdint.h>
+#endif
+
+#define ExecuteNTimes( nTimes, x ) \
+ { \
+ static int __executeCount=0;\
+ if ( __executeCount < nTimes )\
+ { \
+ x; \
+ ++__executeCount; \
+ } \
+ }
+
+
+#define ExecuteOnce( x ) ExecuteNTimes( 1, x )
+
+
+template <typename T>
+inline T AlignValue( T val, uintptr_t alignment )
+{
+ return (T)( ( (uintptr_t)val + alignment - 1 ) & ~( alignment - 1 ) );
+}
+
+
+// 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
+#if !defined(M_PI) && !defined(HAVE_M_PI)
+#define M_PI 3.14159265358979323846
+#endif
+
+#include "valve_minmax_on.h"
+
+// #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
+
+// This is the preferred clamp operator. Using the clamp macro can lead to
+// unexpected side-effects or more expensive code. Even the clamp (all
+// lower-case) function can generate more expensive code because of the
+// mixed types involved.
+template< class T >
+T Clamp( T const &val, T const &minVal, T const &maxVal )
+{
+ if( val < minVal )
+ return minVal;
+ else if( val > maxVal )
+ return maxVal;
+ else
+ return val;
+}
+
+// This is the preferred Min operator. Using the MIN macro can lead to unexpected
+// side-effects or more expensive code.
+template< class T >
+T Min( T const &val1, T const &val2 )
+{
+ return val1 < val2 ? val1 : val2;
+}
+
+// This is the preferred Max operator. Using the MAX macro can lead to unexpected
+// side-effects or more expensive code.
+template< class T >
+T Max( T const &val1, T const &val2 )
+{
+ return val1 > val2 ? val1 : val2;
+}
+
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE (!FALSE)
+#endif
+
+
+#ifndef DONT_DEFINE_BOOL // Needed for Cocoa stuff to compile.
+typedef int BOOL;
+#endif
+
+typedef int qboolean;
+typedef unsigned long ULONG;
+typedef unsigned char BYTE;
+typedef unsigned char byte;
+typedef unsigned short word;
+#ifdef _WIN32
+typedef wchar_t ucs2; // under windows wchar_t is ucs2
+#else
+typedef unsigned short ucs2;
+#endif
+
+enum ThreeState_t
+{
+ TRS_FALSE,
+ TRS_TRUE,
+ TRS_NONE,
+};
+
+typedef float vec_t;
+
+#if defined(__GNUC__)
+#define fpmin __builtin_fminf
+#define fpmax __builtin_fmaxf
+#elif !defined(_X360)
+#define fpmin min
+#define fpmax max
+#endif
+
+
+//-----------------------------------------------------------------------------
+// look for NANs, infinities, and underflows.
+// This assumes the ANSI/IEEE 754-1985 standard
+//-----------------------------------------------------------------------------
+
+inline unsigned long& FloatBits( vec_t& f )
+{
+ return *reinterpret_cast<unsigned long*>(&f);
+}
+
+inline unsigned long const& FloatBits( vec_t const& f )
+{
+ return *reinterpret_cast<unsigned long const*>(&f);
+}
+
+inline vec_t BitsToFloat( unsigned long i )
+{
+ return *reinterpret_cast<vec_t*>(&i);
+}
+
+inline bool IsFinite( vec_t f )
+{
+ return ((FloatBits(f) & 0x7F800000) != 0x7F800000);
+}
+
+inline unsigned long FloatAbsBits( vec_t f )
+{
+ return FloatBits(f) & 0x7FFFFFFF;
+}
+
+// Given today's processors, I cannot think of any circumstance
+// where bit tricks would be faster than fabs. henryg 8/16/2011
+#ifdef _MSC_VER
+#ifndef _In_
+#define _In_
+#endif
+extern "C" float fabsf(_In_ float);
+#else
+#include <math.h>
+#endif
+
+inline float FloatMakeNegative( vec_t f )
+{
+ return -fabsf(f);
+}
+
+inline float FloatMakePositive( vec_t f )
+{
+ return fabsf(f);
+}
+
+inline float FloatNegate( vec_t f )
+{
+ return -f;
+}
+
+
+#define FLOAT32_NAN_BITS (unsigned long)0x7FC00000 // not a number!
+#define FLOAT32_NAN BitsToFloat( FLOAT32_NAN_BITS )
+
+#define VEC_T_NAN FLOAT32_NAN
+
+
+
+// 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;
+} 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(x) (void)(x) // for pesky compiler / lint warnings
+#endif
+
+struct vrect_t
+{
+ int x,y,width,height;
+ vrect_t *pnext;
+};
+
+
+//-----------------------------------------------------------------------------
+// MaterialRect_t struct - used for DrawDebugText
+//-----------------------------------------------------------------------------
+struct Rect_t
+{
+ int x, y;
+ int width, height;
+};
+
+
+//-----------------------------------------------------------------------------
+// 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< unsigned long >
+{
+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
+
+// @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
+
+// 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; }
+
+#include "tier0/valve_on.h"
+
+#endif // BASETYPES_H
diff --git a/public/tier0/commonmacros.h b/public/tier0/commonmacros.h
new file mode 100644
index 0000000..34aec40
--- /dev/null
+++ b/public/tier0/commonmacros.h
@@ -0,0 +1,174 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef COMMONMACROS_H
+#define COMMONMACROS_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+// -------------------------------------------------------
+//
+// 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 SETBITS(iBitVector, bits) ((iBitVector) |= (bits))
+#define CLEARBITS(iBitVector, bits) ((iBitVector) &= ~(bits))
+#define FBitSet(iBitVector, bits) ((iBitVector) & (bits))
+
+template <typename T>
+inline bool IsPowerOfTwo( T value )
+{
+ return (value & ( value - (T)1 )) == (T)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) && \
+ (_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];
+
+#ifdef _PREFAST_
+// The +0 is so that we can go:
+// size = ARRAYSIZE(array) * sizeof(array[0]) without triggering a /analyze
+// warning about multiplying sizeof.
+#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A))+0)
+#else
+#define RTL_NUMBER_OF_V2(A) (sizeof(*RtlpNumberOf(A)))
+#endif
+
+// 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)
+
+#define Q_ARRAYSIZE(p) ARRAYSIZE(p)
+#define V_ARRAYSIZE(p) ARRAYSIZE(p)
+
+template< typename IndexType, typename T, unsigned int N >
+IndexType ClampedArrayIndex( const T (&buffer)[N], IndexType index )
+{
+ NOTE_UNUSED( buffer );
+ return clamp( index, 0, (IndexType)N - 1 );
+}
+
+template< typename T, unsigned int N >
+T ClampedArrayElement( const T (&buffer)[N], unsigned int uIndex )
+{
+ // Put index in an unsigned type to halve the clamping.
+ if ( uIndex >= N )
+ uIndex = N - 1;
+ return buffer[ uIndex ];
+}
+
+#endif // COMMONMACROS_H
diff --git a/public/tier0/cpumonitoring.h b/public/tier0/cpumonitoring.h
new file mode 100644
index 0000000..e6d1c9c
--- /dev/null
+++ b/public/tier0/cpumonitoring.h
@@ -0,0 +1,33 @@
+#ifndef CPU_MONITORING_H
+#define CPU_MONITORING_H
+
+/*
+This header defines functions and structures for controlling the measurement of CPU frequency
+in order to detect thermal throttling. For details see the associated source file.
+*/
+
+struct CPUFrequencyResults
+{
+ double m_timeStamp; // Time (from Plat_FloatTime) when the measurements were made.
+ float m_GHz;
+ float m_percentage;
+ float m_lowestPercentage;
+};
+
+// Call this to get results.
+// When CPU monitoring is 'disabled' it may still be running at a low frequency,
+// for OGS purposes or for proactively warning users of problems. If fGetDisabledResults
+// is true then results will be returned when disabled (if available).
+PLATFORM_INTERFACE CPUFrequencyResults GetCPUFrequencyResults( bool fGetDisabledResults = false );
+
+// Call this to set the monitoring frequency. Intervals of 2-5 seconds (2,000 to 5,000 ms)
+// are recommended. An interval of zero will disable CPU monitoring. Short delays (below
+// about 300 ms) will be rounded up.
+PLATFORM_INTERFACE void SetCPUMonitoringInterval( unsigned nDelayMilliseconds );
+
+// Warn with increasing strident colors when CPU percentages go below these levels.
+// They are const int instead of float because const float in C++ is stupid.
+const int kCPUMonitoringWarning1 = 80;
+const int kCPUMonitoringWarning2 = 50;
+
+#endif
diff --git a/public/tier0/dbg.h b/public/tier0/dbg.h
new file mode 100644
index 0000000..1fff938
--- /dev/null
+++ b/public/tier0/dbg.h
@@ -0,0 +1,820 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef DBG_H
+#define DBG_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "basetypes.h"
+#include "dbgflag.h"
+#include "platform.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef POSIX
+#define __cdecl
+#endif
+
+//-----------------------------------------------------------------------------
+// dll export stuff
+//-----------------------------------------------------------------------------
+#ifndef STATIC_TIER0
+
+#ifdef TIER0_DLL_EXPORT
+#define DBG_INTERFACE DLL_EXPORT
+#define DBG_OVERLOAD DLL_GLOBAL_EXPORT
+#define DBG_CLASS DLL_CLASS_EXPORT
+#else
+#define DBG_INTERFACE DLL_IMPORT
+#define DBG_OVERLOAD DLL_GLOBAL_IMPORT
+#define DBG_CLASS DLL_CLASS_IMPORT
+#endif
+
+#else // BUILD_AS_DLL
+
+#define DBG_INTERFACE extern
+#define DBG_OVERLOAD
+#define DBG_CLASS
+#endif // BUILD_AS_DLL
+
+
+class Color;
+
+
+//-----------------------------------------------------------------------------
+// Usage model for the Dbg library
+//
+// 1. Spew.
+//
+// Spew can be used in a static and a dynamic mode. The static
+// mode allows us to display assertions and other messages either only
+// in debug builds, or in non-release builds. The dynamic mode allows us to
+// turn on and off certain spew messages while the application is running.
+//
+// Static Spew messages:
+//
+// Assertions are used to detect and warn about invalid states
+// Spews are used to display a particular status/warning message.
+//
+// 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).
+//
+// To use a warning, use
+//
+// Warning("Oh I feel so %s all over\n", "yummy");
+//
+// Warning will do its magic in only Debug builds. To perform spew in *all*
+// builds, use RelWarning.
+//
+// Three other spew types, Msg, Log, and Error, are compiled into all builds.
+// These error types do *not* need two sets of parenthesis.
+//
+// Msg( "Isn't this exciting %d?", 5 );
+// Error( "I'm just thrilled" );
+//
+// Dynamic Spew messages
+//
+// It is possible to dynamically turn spew on and off. Dynamic spew is
+// identified by a spew group and priority level. To turn spew on for a
+// particular spew group, use SpewActivate( "group", level ). This will
+// cause all spew in that particular group with priority levels <= the
+// level specified in the SpewActivate function to be printed. Use DSpew
+// to perform the spew:
+//
+// DWarning( "group", level, "Oh I feel even yummier!\n" );
+//
+// Priority level 0 means that the spew will *always* be printed, and group
+// '*' is the default spew group. If a DWarning is encountered using a group
+// whose priority has not been set, it will use the priority of the default
+// group. The priority of the default group is initially set to 0.
+//
+// Spew output
+//
+// The output of the spew system can be redirected to an externally-supplied
+// function which is responsible for outputting the spew. By default, the
+// spew is simply printed using printf.
+//
+// To redirect spew output, call SpewOutput.
+//
+// SpewOutputFunc( OutputFunc );
+//
+// This will cause OutputFunc to be called every time a spew message is
+// generated. OutputFunc will be passed a spew type and a message to print.
+// It must return a value indicating whether the debugger should be invoked,
+// whether the program should continue running, or whether the program
+// should abort.
+//
+// 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();
+//-----------------------------------------------------------------------------
+
+/* Various types of spew messages */
+// I'm sure you're asking yourself why SPEW_ instead of DBG_ ?
+// It's because DBG_ is used all over the place in windows.h
+// For example, DBG_CONTINUE is defined. Feh.
+enum SpewType_t
+{
+ SPEW_MESSAGE = 0,
+ SPEW_WARNING,
+ SPEW_ASSERT,
+ SPEW_ERROR,
+ SPEW_LOG,
+
+ SPEW_TYPE_COUNT
+};
+
+enum SpewRetval_t
+{
+ SPEW_DEBUGGER = 0,
+ SPEW_CONTINUE,
+ SPEW_ABORT
+};
+
+/* type of externally defined function used to display debug spew */
+typedef SpewRetval_t (*SpewOutputFunc_t)( SpewType_t spewType, const tchar *pMsg );
+
+/* Used to redirect spew output */
+DBG_INTERFACE void SpewOutputFunc( SpewOutputFunc_t func );
+
+/* Used to get the current spew output function */
+DBG_INTERFACE SpewOutputFunc_t GetSpewOutputFunc( void );
+
+/* This is the default spew fun, which is used if you don't specify one */
+DBG_INTERFACE SpewRetval_t DefaultSpewFunc( SpewType_t type, const tchar *pMsg );
+
+/* Same as the default spew func, but returns SPEW_ABORT for asserts */
+DBG_INTERFACE SpewRetval_t DefaultSpewFuncAbortOnAsserts( SpewType_t type, const tchar *pMsg );
+
+/* Should be called only inside a SpewOutputFunc_t, returns groupname, level, color */
+DBG_INTERFACE const tchar* GetSpewOutputGroup( void );
+DBG_INTERFACE int GetSpewOutputLevel( void );
+DBG_INTERFACE const Color* GetSpewOutputColor( void );
+
+/* Used to manage spew groups and subgroups */
+DBG_INTERFACE void SpewActivate( const tchar* pGroupName, int level );
+DBG_INTERFACE bool IsSpewActive( const tchar* pGroupName, int level );
+
+/* Used to display messages, should never be called directly. */
+DBG_INTERFACE void _SpewInfo( SpewType_t type, const tchar* pFile, int line );
+DBG_INTERFACE SpewRetval_t _SpewMessage( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE SpewRetval_t _DSpewMessage( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE SpewRetval_t ColorSpewMessage( SpewType_t type, const Color *pColor, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE void _ExitOnFatalAssert( const tchar* pFile, int line );
+DBG_INTERFACE bool ShouldUseNewAssertDialog();
+
+DBG_INTERFACE bool SetupWin32ConsoleIO();
+
+// Returns true if they want to break in the debugger.
+DBG_INTERFACE bool DoNewAssertDialog( const tchar *pFile, int line, const tchar *pExpression );
+
+// Allows the assert dialogs to be turned off from code
+DBG_INTERFACE bool AreAllAssertsDisabled();
+DBG_INTERFACE void SetAllAssertsDisabled( bool bAssertsEnabled );
+
+// Provides a callback that is called on asserts regardless of spew levels
+typedef void (*AssertFailedNotifyFunc_t)( const char *pchFile, int nLine, const char *pchMessage );
+DBG_INTERFACE void SetAssertFailedNotifyFunc( AssertFailedNotifyFunc_t func );
+DBG_INTERFACE void CallAssertFailedNotifyFunc( const char *pchFile, int nLine, const char *pchMessage );
+
+/* True if -hushasserts was passed on command line. */
+DBG_INTERFACE bool HushAsserts();
+
+#if defined( USE_SDL )
+DBG_INTERFACE void SetAssertDialogParent( struct SDL_Window *window );
+DBG_INTERFACE struct SDL_Window * GetAssertDialogParent();
+#endif
+
+/* Used to define macros, never use these directly. */
+
+#ifdef _PREFAST_
+ // When doing /analyze builds define _AssertMsg 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.
+ // The unfortunate !! is necessary because otherwise /analyze is incapable of evaluating
+ // all of the logical expressions that the regular compiler can handle.
+ // Include _msg in the macro so that format errors in it are detected.
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) do { __analysis_assume( !!(_exp) ); _msg; } while (0)
+ #define _AssertMsgOnce( _exp, _msg, _bFatal ) do { __analysis_assume( !!(_exp) ); _msg; } while (0)
+ // Force asserts on for /analyze so that we get a __analysis_assume of all of the constraints.
+ #define DBGFLAG_ASSERT
+ #define DBGFLAG_ASSERTFATAL
+ #define DBGFLAG_ASSERTDEBUG
+#else
+ #define _AssertMsg( _exp, _msg, _executeExp, _bFatal ) \
+ do { \
+ if (!(_exp)) \
+ { \
+ _SpewInfo( SPEW_ASSERT, __TFILE__, __LINE__ ); \
+ SpewRetval_t retAssert = _SpewMessage("%s", static_cast<const char*>( _msg )); \
+ CallAssertFailedNotifyFunc( __TFILE__, __LINE__, _msg ); \
+ _executeExp; \
+ if ( retAssert == SPEW_DEBUGGER) \
+ { \
+ if ( !ShouldUseNewAssertDialog() || DoNewAssertDialog( __TFILE__, __LINE__, _msg ) ) \
+ { \
+ DebuggerBreak(); \
+ } \
+ if ( _bFatal ) \
+ { \
+ _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, (const tchar *)CDbgFmtMsg( _msg, ##__VA_ARGS__ ), ((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, _msg, a1 )
+#define AssertFatalMsg2( _exp, _msg, a1, a2 ) AssertFatalMsg( _exp, _msg, a1, a2 )
+#define AssertFatalMsg3( _exp, _msg, a1, a2, a3 ) AssertFatalMsg( _exp, _msg, a1, a2, a3 )
+#define AssertFatalMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4 )
+#define AssertFatalMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5 )
+#define AssertFatalMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6 )
+#define AssertFatalMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 )
+#define AssertFatalMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertFatalMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 )
+#define AssertFatalMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertFatalMsg( _exp, _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 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
+
+// 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, (const tchar *)CDbgFmtMsg( _msg, ##__VA_ARGS__ ), ((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 VerifyMsg1( _exp, _msg, a1 ) AssertMsg1( _exp, _msg, a1 )
+#define VerifyMsg2( _exp, _msg, a1, a2 ) AssertMsg2( _exp, _msg, a1, a2 )
+#define VerifyMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg3( _exp, _msg, a1, a2, a3 )
+#define VerifyEquals( _exp, _expectedValue ) AssertEquals( _exp, _expectedValue )
+#define DbgVerify( _exp ) Assert( _exp )
+
+#define AssertMsg1( _exp, _msg, a1 ) AssertMsg( _exp, _msg, a1 )
+#define AssertMsg2( _exp, _msg, a1, a2 ) AssertMsg( _exp, _msg, a1, a2 )
+#define AssertMsg3( _exp, _msg, a1, a2, a3 ) AssertMsg( _exp, _msg, a1, a2, a3 )
+#define AssertMsg4( _exp, _msg, a1, a2, a3, a4 ) AssertMsg( _exp, _msg, a1, a2, a3, a4 )
+#define AssertMsg5( _exp, _msg, a1, a2, a3, a4, a5 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5 )
+#define AssertMsg6( _exp, _msg, a1, a2, a3, a4, a5, a6 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6 )
+#define AssertMsg7( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7 )
+#define AssertMsg8( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 ) AssertMsg( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8 )
+#define AssertMsg9( _exp, _msg, a1, a2, a3, a4, a5, a6, a7, a8, a9 ) AssertMsg( _exp, _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 VerifyMsg1( _exp, _msg, a1 ) (_exp)
+#define VerifyMsg2( _exp, _msg, a1, a2 ) (_exp)
+#define VerifyMsg3( _exp, _msg, a1, a2, a3 ) (_exp)
+#define VerifyEquals( _exp, _expectedValue ) (_exp)
+#define DbgVerify( _exp ) (_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
+
+// The Always version of the assert macros are defined even when DBGFLAG_ASSERT is not,
+// so they will be available even in release.
+#define AssertAlways( _exp ) _AssertMsg( _exp, _T("Assertion Failed: ") _T(#_exp), ((void)0), false )
+#define AssertMsgAlways( _exp, _msg ) _AssertMsg( _exp, _msg, ((void)0), false )
+
+// Stringify a number
+#define V_STRINGIFY_INTERNAL(x) #x
+// Extra level of indirection needed when passing in a macro to avoid getting the macro name instead of value
+#define V_STRINGIFY(x) V_STRINGIFY_INTERNAL(x)
+
+// Macros to help decorate warnings or errors with the location in code
+#define FILE_LINE_FUNCTION_STRING __FILE__ "(" V_STRINGIFY(__LINE__) "):" __FUNCTION__ ":"
+#define FILE_LINE_STRING __FILE__ "(" V_STRINGIFY(__LINE__) "):"
+#define FUNCTION_LINE_STRING __FUNCTION__ "(" V_STRINGIFY(__LINE__) "): "
+
+// Handy define for inserting clickable messages into the build output.
+// Use like this:
+// #pragma MESSAGE("Some message")
+#define MESSAGE(msg) message(__FILE__ "(" V_STRINGIFY(__LINE__) "): " msg)
+
+
+#if !defined( _X360 ) || !defined( _RETAIL )
+
+/* These are always compiled in */
+DBG_INTERFACE void Msg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void DMsg( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
+
+DBG_INTERFACE void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void DWarning( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
+
+DBG_INTERFACE void Log( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void DLog( const tchar *pGroupName, int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
+
+#ifdef Error
+// p4.cpp does a #define Error Warning and in that case the Error prototype needs to
+// be consistent with the Warning prototype.
+DBG_INTERFACE void Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+#else
+DBG_INTERFACE void NORETURN Error( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void NORETURN ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist );
+
+#endif
+
+#else
+
+inline void Msg( ... ) {}
+inline void DMsg( ... ) {}
+inline void MsgV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
+inline void Warning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) {}
+inline void WarningV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
+inline void DWarning( ... ) {}
+inline void Log( ... ) {}
+inline void DLog( ... ) {}
+inline void LogV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
+inline void Error( ... ) {}
+inline void ErrorV( PRINTF_FORMAT_STRING const tchar *pMsg, va_list arglist ) {}
+
+#endif
+
+// 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; \
+ }
+
+#if !defined( _X360 ) || !defined( _RETAIL )
+
+/* A couple of super-common dynamic spew messages, here for convenience */
+/* These looked at the "developer" group */
+DBG_INTERFACE void DevMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void DevWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void DevLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+/* default level versions (level 1) */
+DBG_OVERLOAD void DevMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_OVERLOAD void DevWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_OVERLOAD void DevLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+/* These looked at the "console" group */
+DBG_INTERFACE void ConColorMsg( int level, const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 3, 4 );
+DBG_INTERFACE void ConMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void ConWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void ConLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+/* default console version (level 1) */
+DBG_OVERLOAD void ConColorMsg( const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_OVERLOAD void ConMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_OVERLOAD void ConWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_OVERLOAD void ConLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+/* developer console version (level 2) */
+DBG_INTERFACE void ConDColorMsg( const Color& clr, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void ConDMsg( PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void ConDWarning( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+DBG_INTERFACE void ConDLog( PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 1, 2 );
+
+/* These looked at the "network" group */
+DBG_INTERFACE void NetMsg( int level, PRINTF_FORMAT_STRING const tchar* pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void NetWarning( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+DBG_INTERFACE void NetLog( int level, PRINTF_FORMAT_STRING const tchar *pMsg, ... ) FMTFUNCTION( 2, 3 );
+
+void ValidateSpew( class CValidator &validator );
+
+#else
+
+inline void DevMsg( ... ) {}
+inline void DevWarning( ... ) {}
+inline void DevLog( ... ) {}
+inline void ConMsg( ... ) {}
+inline void ConLog( ... ) {}
+inline void NetMsg( ... ) {}
+inline void NetWarning( ... ) {}
+inline void NetLog( ... ) {}
+
+#endif
+
+DBG_INTERFACE void COM_TimestampedLog( PRINTF_FORMAT_STRING char const *fmt, ... ) FMTFUNCTION( 1, 2 );
+
+/* Code macros, debugger interface */
+
+#ifdef DBGFLAG_ASSERT
+
+#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 */
+
+//-----------------------------------------------------------------------------
+
+#ifndef _RETAIL
+class CScopeMsg
+{
+public:
+ CScopeMsg( const char *pszScope )
+ {
+ m_pszScope = pszScope;
+ Msg( "%s { ", pszScope );
+ }
+ ~CScopeMsg()
+ {
+ Msg( "} %s", m_pszScope );
+ }
+ const char *m_pszScope;
+};
+#define SCOPE_MSG( msg ) CScopeMsg scopeMsg( msg )
+#else
+#define SCOPE_MSG( msg )
+#endif
+
+
+//-----------------------------------------------------------------------------
+// This macro predates universal static_assert support in our toolchains
+#define COMPILE_TIME_ASSERT( pred ) static_assert( pred, "Compile time assert constraint is not true: " #pred )
+
+// ASSERT_INVARIANT used to be needed in order to allow COMPILE_TIME_ASSERTs at global
+// scope. However the new COMPILE_TIME_ASSERT macro supports that by default.
+#define ASSERT_INVARIANT( pred ) COMPILE_TIME_ASSERT( pred )
+
+// NOTE: On GCC / Clang, assert_cast can sometimes fire even if the type is correct. We should just workaround these.
+// The situation where this would occur is
+// 1. You create an object of a low level type in a DLL, and it really gets created there.
+// 2. You pass it across a DLL boundary
+// 3. You use assert_cast to verify it in the second DLL boundary (where it also could've been created).
+#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.
+
+DBG_INTERFACE void _AssertValidReadPtr( void* ptr, int count = 1 );
+DBG_INTERFACE void _AssertValidWritePtr( void* ptr, int count = 1 );
+DBG_INTERFACE void _AssertValidReadWritePtr( void* ptr, int count = 1 );
+DBG_INTERFACE void AssertValidStringPtr( const tchar* ptr, int maxchar = 0xFFFFFF );
+
+#ifdef DBGFLAG_ASSERT
+
+FORCEINLINE void AssertValidReadPtr( const void* ptr, int count = 1 ) { _AssertValidReadPtr( (void*)ptr, count ); }
+FORCEINLINE void AssertValidWritePtr( const void* ptr, int count = 1 ) { _AssertValidWritePtr( (void*)ptr, count ); }
+FORCEINLINE void AssertValidReadWritePtr( const void* ptr, int count = 1 ) { _AssertValidReadWritePtr( (void*)ptr, count ); }
+
+#else
+
+FORCEINLINE void AssertValidReadPtr( const void* ptr, int count = 1 ) { }
+FORCEINLINE void AssertValidWritePtr( const void* ptr, int count = 1 ) { }
+FORCEINLINE void AssertValidReadWritePtr( const void* ptr, int count = 1 ) { }
+#define AssertValidStringPtr AssertValidReadPtr
+
+#endif
+
+#define AssertValidThis() AssertValidReadWritePtr(this,sizeof(*this))
+
+//-----------------------------------------------------------------------------
+// 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
+
+//-----------------------------------------------------------------------------
+//
+// Purpose: Inline string formatter
+//
+
+#include "tier0/valve_off.h"
+class CDbgFmtMsg
+{
+public:
+ CDbgFmtMsg(PRINTF_FORMAT_STRING const tchar *pszFormat, ...) FMTFUNCTION( 2, 3 )
+ {
+ va_list arg_ptr;
+
+ va_start(arg_ptr, pszFormat);
+ _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
+
+//-----------------------------------------------------------------------------
+
+
+// This is horrible, but we don't want to integrate CS:GO new logging system atm.
+#define Log_Warning( ignore, ... ) ::Msg( __VA_ARGS__ ); ::Log( __VA_ARGS__ );
+#define Log_Msg( ignore, ... ) ::Warning( __VA_ARGS__ ); ::Log( __VA_ARGS__ );
+#define Log_Error( ignore, ... ) ::Error( __VA_ARGS__ );
+#define DEFINE_LOGGING_CHANNEL_NO_TAGS( ... );
+#define Plat_FatalError( ... ) do { Log_Error( LOG_GENERAL, __VA_ARGS__ ); Plat_ExitProcess( EXIT_FAILURE ); } while( 0 )
+
+#endif /* DBG_H */
diff --git a/public/tier0/dbgflag.h b/public/tier0/dbgflag.h
new file mode 100644
index 0000000..05f84c9
--- /dev/null
+++ b/public/tier0/dbgflag.h
@@ -0,0 +1,65 @@
+//========= Copyright 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( RELEASEASSERTS ) )
+
+#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
+
+#endif // DBGFLAG_H
diff --git a/public/tier0/dynfunction.h b/public/tier0/dynfunction.h
new file mode 100644
index 0000000..bd976b7
--- /dev/null
+++ b/public/tier0/dynfunction.h
@@ -0,0 +1,136 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+// This makes it easy to dynamically load a shared library and lookup a
+// function in that library.
+//
+// Usage:
+// CDynamicFunction<void (*)(const char *)> MyPuts(libname, "puts");
+// if (MyPuts)
+// MyPuts("Hello world!");
+//
+// Please note that this interface does not distinguish between functions and
+// data. If you look up a global variable in your shared library, or simply
+// mess up the function signature, you'll get a valid pointer and a crash
+// if you call it as a function.
+
+#ifndef DYNFUNCTION_H
+#define DYNFUNCTION_H
+#pragma once
+
+#include "tier0/platform.h"
+
+// The heavy lifting isn't template-specific, so we move it out of the header.
+DLL_EXPORT void *VoidFnPtrLookup_Tier0(const char *libname, const char *fn, void *fallback);
+
+template < class FunctionType >
+class CDynamicFunction
+{
+public:
+ // Construct with a NULL function pointer. You must manually call
+ // Lookup() before you can call a dynamic function through this interface.
+ CDynamicFunction() : m_pFn(NULL) {}
+
+ // Construct and do a lookup right away. You will need to make sure that
+ // the lookup actually succeeded, as (libname) might have failed to load
+ // or (fn) might not exist in it.
+ CDynamicFunction(const char *libname, const char *fn, FunctionType fallback=NULL) : m_pFn(NULL)
+ {
+ Lookup(libname, fn, fallback);
+ }
+
+ // Construct and do a lookup right away. See comments in Lookup() about what (okay) does.
+ CDynamicFunction(const char *libname, const char *fn, bool &okay, FunctionType fallback=NULL) : m_pFn(NULL)
+ {
+ Lookup(libname, fn, okay, fallback);
+ }
+
+ // Load library if necessary, look up symbol. Returns true and sets
+ // m_pFn on successful lookup, returns false otherwise. If the
+ // function pointer is already looked up, this return true immediately.
+ // Use Reset() first if you want to look up the symbol again.
+ // This function will return false immediately unless (okay) is true.
+ // This allows you to chain lookups like this:
+ // bool okay = true;
+ // x.Lookup(lib, "x", okay);
+ // y.Lookup(lib, "y", okay);
+ // z.Lookup(lib, "z", okay);
+ // if (okay) { printf("All functions were loaded successfully!\n"); }
+ // If you supply a fallback, it'll be used if the lookup fails (and if
+ // non-NULL, means this will always return (okay)).
+ bool Lookup(const char *libname, const char *fn, bool &okay, FunctionType fallback=NULL)
+ {
+ if (!okay)
+ return false;
+ else if (m_pFn == NULL)
+ m_pFn = (FunctionType) VoidFnPtrLookup_Tier0(libname, fn, (void *) fallback);
+ okay = m_pFn != NULL;
+ return okay;
+ }
+
+ // Load library if necessary, look up symbol. Returns true and sets
+ // m_pFn on successful lookup, returns false otherwise. If the
+ // function pointer is already looked up, this return true immediately.
+ // Use Reset() first if you want to look up the symbol again.
+ // This function will return false immediately unless (okay) is true.
+ // If you supply a fallback, it'll be used if the lookup fails (and if
+ // non-NULL, means this will always return true).
+ bool Lookup(const char *libname, const char *fn, FunctionType fallback=NULL)
+ {
+ bool okay = true;
+ return Lookup(libname, fn, okay, fallback);
+ }
+
+ // Invalidates the current lookup. Makes the function pointer NULL. You
+ // will need to call Lookup() before you can call a dynamic function
+ // through this interface again.
+ void Reset() { m_pFn = NULL; }
+
+ // Force this to be a specific function pointer.
+ void Force(FunctionType ptr) { m_pFn = ptr; }
+
+ // Retrieve the actual function pointer.
+ FunctionType Pointer() const { return m_pFn; }
+ operator FunctionType() const { return m_pFn; }
+
+ // Can be used to verify that we have an actual function looked up and
+ // ready to call: if (!MyDynFunc) { printf("Function not found!\n"); }
+ operator bool () const { return m_pFn != NULL; }
+ bool operator !() const { return m_pFn == NULL; }
+
+protected:
+ FunctionType m_pFn;
+};
+
+
+// This is the same as CDynamicFunction, but we made the default constructor
+// private, forcing you to do loading/lookup during construction.
+// The usage pattern is to have a list of dynamic functions that are
+// constructed en masse as part of another class's constructor, with the
+// possibility of human error removed (the compiler will complain if you
+// forget to initialize one).
+template < class FunctionType >
+class CDynamicFunctionMustInit : public CDynamicFunction < FunctionType >
+{
+private: // forbid default constructor.
+ CDynamicFunctionMustInit() {}
+
+public:
+ CDynamicFunctionMustInit(const char *libname, const char *fn, FunctionType fallback=NULL)
+ : CDynamicFunction< FunctionType >(libname, fn, fallback)
+ {
+ }
+
+ CDynamicFunctionMustInit(const char *libname, const char *fn, bool &okay, FunctionType fallback=NULL)
+ : CDynamicFunction< FunctionType >(libname, fn, okay, fallback)
+ {
+ }
+};
+
+#endif // DYNFUNCTION_H
+
diff --git a/public/tier0/etwprof.h b/public/tier0/etwprof.h
new file mode 100644
index 0000000..c1d4282
--- /dev/null
+++ b/public/tier0/etwprof.h
@@ -0,0 +1,157 @@
+//========= Copyright 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.
+#define ETW_MARKS_ENABLED
+#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 void 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 synchronizing
+// 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 ETWMouseMove( int nX, int nY );
+PLATFORM_INTERFACE void ETWMouseWheel( int nWheelDelta, 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 void ETWMarkPrintf( const char *, ... ) { return; }
+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 ETWMouseMove( int nX, int nY ) {}
+inline void ETWMouseWheel( int nWheelDelta, 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/public/tier0/fasttimer.h b/public/tier0/fasttimer.h
new file mode 100644
index 0000000..e9e634f
--- /dev/null
+++ b/public/tier0/fasttimer.h
@@ -0,0 +1,569 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef FASTTIMER_H
+#define FASTTIMER_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifdef _WIN32
+#include <intrin.h>
+#endif
+
+#include <assert.h>
+#include "tier0/platform.h"
+
+PLATFORM_INTERFACE uint64 g_ClockSpeed;
+#if defined( _X360 ) && defined( _CERT )
+PLATFORM_INTERFACE unsigned long g_dwFakeFastCounter;
+#endif
+
+PLATFORM_INTERFACE double g_ClockSpeedMicrosecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedMillisecondsMultiplier;
+PLATFORM_INTERFACE double g_ClockSpeedSecondsMultiplier;
+
+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 PLATFORM_CLASS CClockSpeedInit
+{
+public:
+ CClockSpeedInit()
+ {
+ Init();
+ }
+
+ static void Init();
+};
+
+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 int64 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;
+};
+
+// -------------------------------------------------------------------------- //
+
+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;
+}
+
+inline void CCycleCount::Sample()
+{
+ m_Int64 = Plat_Rdtsc();
+}
+
+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 int64 CFastTimer::GetClockSpeed()
+{
+ return g_ClockSpeed;
+}
+
+
+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. NOTE: CMicroSecOverage() and CMicroSecLeft() are not as fast to check.
+class CLimitTimer
+{
+public:
+ CLimitTimer() {}
+ CLimitTimer( uint64 cMicroSecDuration ) { SetLimit( cMicroSecDuration ); }
+ void SetLimit( uint64 m_cMicroSecDuration );
+ bool BLimitReached() const;
+
+ int CMicroSecOverage() const;
+ uint64 CMicroSecLeft() const;
+
+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 cMicroSecDuration )
+{
+ uint64 dlCycles = ( ( uint64 ) cMicroSecDuration * g_ClockSpeed ) / ( 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() const
+{
+ CCycleCount cycleCount;
+ cycleCount.Sample( );
+ return ( cycleCount.GetLongCycles( ) >= m_lCycleLimit );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: If we're over our specified time period, return the amount of the overage.
+// Output: # of microseconds since we reached our specified time period.
+//-----------------------------------------------------------------------------
+inline int CLimitTimer::CMicroSecOverage() const
+{
+ CCycleCount cycleCount;
+ cycleCount.Sample();
+ uint64 lcCycles = cycleCount.GetLongCycles();
+
+ if ( lcCycles < m_lCycleLimit )
+ return 0;
+
+ return( ( int ) ( ( lcCycles - m_lCycleLimit ) * ( uint64 ) 1000000L / g_ClockSpeed ) );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: If we're under our specified time period, return the amount under.
+// Output: # of microseconds until we reached our specified time period, 0 if we've passed it
+//-----------------------------------------------------------------------------
+inline uint64 CLimitTimer::CMicroSecLeft() const
+{
+ CCycleCount cycleCount;
+ cycleCount.Sample();
+ uint64 lcCycles = cycleCount.GetLongCycles();
+
+ if ( lcCycles >= m_lCycleLimit )
+ return 0;
+
+ return( ( uint64 ) ( ( m_lCycleLimit - lcCycles ) * ( uint64 ) 1000000L / g_ClockSpeed ) );
+}
+
+
+#endif // FASTTIMER_H
diff --git a/public/tier0/ia32detect.h b/public/tier0/ia32detect.h
new file mode 100644
index 0000000..dd603d1
--- /dev/null
+++ b/public/tier0/ia32detect.h
@@ -0,0 +1,377 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+#ifndef IA32DETECT_H
+#define IA32DETECT_H
+
+#ifdef PLATFORM_WINDOWS_PC
+#include <intrin.h>
+#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;
+
+ int data[4 + 1];
+ tchar * s1;
+
+ s1 = (tchar *) &data[1];
+ __cpuid(data, 0);
+ data[4] = 0;
+ // Returns something like this:
+ // data[0] = 0x0000000b
+ // data[1] = 0x756e6547 Genu
+ // data[2] = 0x6c65746e ntel
+ // data[3] = 0x49656e69 ineI
+ // data[4] = 0x00000000
+
+ m = data[0];
+ int t = data[2];
+ data[2] = data[3];
+ data[3] = t;
+ vendor_name = s1;
+ 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/public/tier0/icommandline.h b/public/tier0/icommandline.h
new file mode 100644
index 0000000..0cb54cf
--- /dev/null
+++ b/public/tier0/icommandline.h
@@ -0,0 +1,61 @@
+//========= Copyright 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;
+ // A bool return of whether param exists, useful for just checking if param that is just a flag is set
+ virtual bool HasParm( const char *psz ) 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;
+
+ virtual const char *ParmValueByIndex( int nIndex, const char *pDefaultVal = 0 ) const = 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_Tier0();
+
+#if !defined( VSTDLIB_BACKWARD_COMPAT )
+#define CommandLine CommandLine_Tier0
+#endif
+
+#endif // TIER0_ICOMMANDLINE_H
+
diff --git a/public/tier0/l2cache.h b/public/tier0/l2cache.h
new file mode 100644
index 0000000..2ee8833
--- /dev/null
+++ b/public/tier0/l2cache.h
@@ -0,0 +1,46 @@
+//========= Copyright 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/public/tier0/mem.h b/public/tier0/mem.h
new file mode 100644
index 0000000..3161241
--- /dev/null
+++ b/public/tier0/mem.h
@@ -0,0 +1,47 @@
+//========= Copyright 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();
+MEM_INTERFACE void MemAllocOOMError( size_t nSize );
+
+#ifdef _LINUX
+MEM_INTERFACE void ZeroMemory( void *mem, size_t length );
+#endif
+
+
+#endif /* TIER0_MEM_H */
diff --git a/public/tier0/memalloc.h b/public/tier0/memalloc.h
new file mode 100644
index 0000000..0a1c089
--- /dev/null
+++ b/public/tier0/memalloc.h
@@ -0,0 +1,661 @@
+//========= Copyright 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 POSIX
+// Define this in release to get memory tracking even in release builds
+//#define USE_MEM_DEBUG 1
+#endif
+
+#if defined( _MEMTEST )
+#ifdef _WIN32
+#define USE_MEM_DEBUG 1
+#endif
+#endif
+
+// Undefine this if using a compiler lacking threadsafe RTTI (like vc6)
+#define MEM_DEBUG_CLASSNAME 1
+
+#include <stddef.h>
+#if defined( OSX )
+#include <malloc/malloc.h>
+#endif
+
+#include "tier0/mem.h"
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+struct _CrtMemState;
+
+#define MEMALLOC_VERSION 1
+
+typedef size_t (*MemAllocFailHandler_t)( size_t );
+
+//-----------------------------------------------------------------------------
+// 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;
+ 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;
+ 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;
+
+ // Returns size of a particular allocation
+ 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 long CrtSetBreakAlloc( long 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;
+
+ // 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, int nLogicalSize, int nActualSize, unsigned nTime ) = 0;
+ virtual void RegisterDeallocation( const char *pFileName, int nLine, int nLogicalSize, int 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;
+
+#if defined( _MEMTEST )
+ virtual void SetStatsExtraInfo( const char *pMapName, const char *pComment ) = 0;
+#endif
+
+ // Returns 0 if no failure, otherwise the size_t of the last requested chunk
+ // "I'm sure this is completely thread safe!" Brian Deen 7/19/2012.
+ virtual size_t MemoryAllocFailed() = 0;
+
+ // 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;
+
+ // Replacement for ::GlobalMemoryStatus which accounts for unused memory in our system
+ virtual void GlobalMemoryStatus( size_t *pUsedMemory, size_t *pFreeMemory ) = 0;
+};
+
+//-----------------------------------------------------------------------------
+// Singleton interface
+//-----------------------------------------------------------------------------
+MEM_INTERFACE IMemAlloc *g_pMemAlloc;
+
+//-----------------------------------------------------------------------------
+
+#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->Alloc( nSize );
+}
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->Alloc( nSize, pFileName, nLine );
+}
+#endif
+inline void MemAlloc_Free( void *ptr )
+{
+ g_pMemAlloc->Free( ptr );
+}
+inline void MemAlloc_Free( void *ptr, const char *pFileName, int nLine )
+{
+ g_pMemAlloc->Free( ptr, pFileName, nLine );
+}
+
+//-----------------------------------------------------------------------------
+
+inline bool ValueIsPowerOfTwo( size_t value ) // don't clash with mathlib definition
+{
+ return (value & ( value - 1 )) == 0;
+}
+
+inline void *MemAlloc_AllocAligned( size_t size, size_t align )
+{
+ unsigned char *pAlloc, *pResult;
+
+ if (!IsPowerOfTwo(align))
+ return NULL;
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)g_pMemAlloc->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;
+}
+
+inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile, int nLine )
+{
+ unsigned char *pAlloc, *pResult;
+
+ if (!IsPowerOfTwo(align))
+ return NULL;
+
+ align = (align > sizeof(void *) ? align : sizeof(void *)) - 1;
+
+ if ( (pAlloc = (unsigned char*)g_pMemAlloc->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;
+}
+
+inline void *MemAlloc_AllocAlignedUnattributed( size_t size, size_t align )
+{
+ unsigned char *pAlloc, *pResult;
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+ 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;
+}
+
+inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile, int nLine )
+{
+ unsigned char *pAlloc, *pResult;
+
+ if (!ValueIsPowerOfTwo(align))
+ return NULL;
+
+ 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;
+}
+
+inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
+{
+ if ( !IsPowerOfTwo( align ) )
+ return NULL;
+
+ // Don't change alignment between allocation + reallocation.
+ if ( ( (size_t)ptr & ( align - 1 ) ) != 0 )
+ return NULL;
+
+ 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;
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock )
+{
+ 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 );
+}
+
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pFileName, int nLine )
+{
+ 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, pFileName, nLine );
+}
+
+inline size_t MemAlloc_GetSizeAligned( void *pMemBlock )
+{
+ 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 );
+}
+
+//-----------------------------------------------------------------------------
+
+#if (defined(_DEBUG) || defined(USE_MEM_DEBUG))
+#define MEM_ALLOC_CREDIT_JOIN_AGAIN( a, b ) a ## b
+#define MEM_ALLOC_CREDIT_JOIN( a, b ) MEM_ALLOC_CREDIT_JOIN_AGAIN( a, b )
+#define MEM_ALLOC_CREDIT_(tag) CMemAllocAttributeAlloction MEM_ALLOC_CREDIT_JOIN( memAllocAttributeAlloction, __LINE__ )( 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
+
+#define MemAlloc_DumpStats() g_pMemAlloc->DumpStats()
+#define MemAlloc_CompactHeap() g_pMemAlloc->CompactHeap()
+#define MemAlloc_CompactIncremental() g_pMemAlloc->CompactIncremental()
+#define MemAlloc_DumpStatsFileBase( _filename ) g_pMemAlloc->DumpStatsFileBase( _filename )
+#define MemAlloc_CrtCheckMemory() g_pMemAlloc->CrtCheckMemory()
+#define MemAlloc_GlobalMemoryStatus( _usedMemory, _freeMemory ) g_pMemAlloc->GlobalMemoryStatus( _usedMemory, _freeMemory )
+#define MemAlloc_MemoryAllocFailed() g_pMemAlloc->MemoryAllocFailed()
+
+#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
+#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
+#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
+#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
+#define MemAlloc_GetSize( x ) g_pMemAlloc->GetSize( x );
+//-----------------------------------------------------------------------------
+
+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(_WIN32) && ( 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)
+ #define MEM_ALLOC_CREDIT_CLASS() MEM_ALLOC_CREDIT_( typeid(*this).name() )
+ #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> g_##tag##Allocs( DefLessFunc( void *) ); \
+ static const char *g_psz##tag##Alloc = strcpy( (char *)g_pMemAlloc->Alloc( strlen( #tag "Alloc" ) + 1, "intentional leak", 0 ), #tag "Alloc" );
+
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ g_pMemAlloc->GetActualDbgInfo( fileLine.pszFile, fileLine.line ); \
+ if ( fileLine.pszFile != g_psz##tag##Alloc ) \
+ { \
+ g_##tag##Allocs.Insert( p, fileLine ); \
+ } \
+ \
+ MemAlloc_RegisterAllocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) \
+ if ( !p ) \
+ ; \
+ else \
+ { \
+ MemAllocFileLine_t fileLine = { g_psz##tag##Alloc, 0 }; \
+ CUtlMap<void *, MemAllocFileLine_t, int>::IndexType_t iRecordedFileLine = g_##tag##Allocs.Find( p ); \
+ if ( iRecordedFileLine != g_##tag##Allocs.InvalidIndex() ) \
+ { \
+ fileLine = g_##tag##Allocs[iRecordedFileLine]; \
+ g_##tag##Allocs.RemoveAt( iRecordedFileLine ); \
+ } \
+ \
+ MemAlloc_RegisterDeallocation( fileLine.pszFile, fileLine.line, size, size, 0); \
+ }
+
+#else
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+#endif
+
+//-----------------------------------------------------------------------------
+
+#elif defined( POSIX )
+
+inline void MemAlloc_CheckAlloc( void *ptr, size_t nSize )
+{
+ if ( !ptr )
+ MemAllocOOMError( nSize );
+}
+
+#if defined( OSX )
+// Mac always aligns allocs, don't need to call posix_memalign which doesn't exist in 10.5.8 which TF2 still needs to run on
+//inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; posix_memalign(&pTmp, alignment, size); return pTmp;}
+inline void *memalign(size_t alignment, size_t size) {void *pTmp=NULL; pTmp = malloc(size); MemAlloc_CheckAlloc( pTmp, size ); return pTmp;}
+#endif
+
+inline void *_aligned_malloc( size_t nSize, size_t align ) { void *ptr = memalign( align, nSize ); MemAlloc_CheckAlloc( ptr, nSize ); return ptr; }
+inline void _aligned_free( void *ptr ) { free( ptr ); }
+
+inline void *MemAlloc_Alloc( size_t nSize, const char *pFileName = NULL, int nLine = 0 ) { void *ptr = malloc( nSize ); MemAlloc_CheckAlloc( ptr, nSize ); return ptr; }
+inline void MemAlloc_Free( void *ptr, const char *pFileName = NULL, int nLine = 0 ) { free( ptr ); }
+
+inline void *MemAlloc_AllocAligned( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { void *ptr = memalign( align, size ); MemAlloc_CheckAlloc( ptr, size ); return ptr; }
+inline void *MemAlloc_AllocAlignedFileLine( size_t size, size_t align, const char *pszFile = NULL, int nLine = 0 ) { void *ptr = memalign( align, size ); MemAlloc_CheckAlloc( ptr, size ); return ptr; }
+inline void MemAlloc_FreeAligned( void *pMemBlock, const char *pszFile = NULL, int nLine = 0 ) { free( pMemBlock ); }
+
+#if defined( OSX )
+inline size_t _msize( void *ptr ) { return malloc_size( ptr ); }
+#else
+inline size_t _msize( void *ptr ) { return malloc_usable_size( ptr ); }
+#endif
+
+inline void *MemAlloc_ReallocAligned( void *ptr, size_t size, size_t align )
+{
+ void *ptr_new_aligned = memalign( align, size );
+
+ if( ptr_new_aligned )
+ {
+ size_t old_size = _msize( ptr );
+ size_t copy_size = ( size < old_size ) ? size : old_size;
+
+ memcpy( ptr_new_aligned, ptr, copy_size );
+ free( ptr );
+ }
+
+ MemAlloc_CheckAlloc( ptr_new_aligned, size );
+ return ptr_new_aligned;
+}
+#else
+#define MemAlloc_GetDebugInfoSize() g_pMemAlloc->GetDebugInfoSize()
+#define MemAlloc_SaveDebugInfo( pvDebugInfo ) g_pMemAlloc->SaveDebugInfo( pvDebugInfo )
+#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) g_pMemAlloc->RestoreDebugInfo( pvDebugInfo )
+#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) g_pMemAlloc->InitDebugInfo( pvDebugInfo, pchRootFileName, nLine )
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+#if !defined(STEAM) && defined(NO_MALLOC_OVERRIDE)
+
+#define MEM_ALLOC_CREDIT_(tag) ((void)0)
+#define MEM_ALLOC_CREDIT() MEM_ALLOC_CREDIT_(__FILE__)
+#define MEM_ALLOC_CREDIT_FUNCTION()
+#define MEM_ALLOC_CREDIT_CLASS()
+#define MEM_ALLOC_CLASSNAME(type) NULL
+
+#define MemAlloc_PushAllocDbgInfo( pszFile, line )
+#define MemAlloc_PopAllocDbgInfo()
+#define MemAlloc_RegisterAllocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#define MemAlloc_RegisterDeallocation( pFileName, nLine, nLogicalSize, nActualSize, nTime ) ((void)0)
+#define MemAlloc_DumpStats() ((void)0)
+#define MemAlloc_CompactHeap() ((void)0)
+#define MemAlloc_CompactIncremental() ((void)0)
+#define MemAlloc_DumpStatsFileBase( _filename ) ((void)0)
+inline bool MemAlloc_CrtCheckMemory() { return true; }
+inline void MemAlloc_GlobalMemoryStatus( size_t *pusedMemory, size_t *pfreeMemory )
+{
+ *pusedMemory = 0;
+ *pfreeMemory = 0;
+}
+#define MemAlloc_MemoryAllocFailed() 0
+
+#define MemAlloc_GetDebugInfoSize() 0
+#define MemAlloc_SaveDebugInfo( pvDebugInfo ) ((void)0)
+#define MemAlloc_RestoreDebugInfo( pvDebugInfo ) ((void)0)
+#define MemAlloc_InitDebugInfo( pvDebugInfo, pchRootFileName, nLine ) ((void)0)
+
+
+#define MEMALLOC_DEFINE_EXTERNAL_TRACKING( tag )
+#define MemAlloc_RegisterExternalAllocation( tag, p, size ) ((void)0)
+#define MemAlloc_RegisterExternalDeallocation( tag, p, size ) ((void)0)
+
+#endif // !STEAM && NO_MALLOC_OVERRIDE
+
+//-----------------------------------------------------------------------------
+
+
+
+// linux memory tracking via hooks.
+#if defined( POSIX ) && !defined( NO_HOOK_MALLOC )
+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 );
+
+#else
+FORCEINLINE void MemoryLogMessage( char const *s )
+{
+}
+
+FORCEINLINE void EnableMemoryLogging( bool bOnOff )
+{
+}
+FORCEINLINE void DumpMemoryLog( int nThresh )
+{
+}
+FORCEINLINE void DumpMemorySummary( void )
+{
+}
+FORCEINLINE void SetMemoryMark( void )
+{
+}
+FORCEINLINE void DumpChangedMemory( int nThresh )
+{
+}
+
+#endif
+
+#ifdef POSIX
+// ApproximateProcessMemoryUsage returns the approximate memory footprint of this process.
+PLATFORM_INTERFACE size_t ApproximateProcessMemoryUsage( void );
+#else
+FORCEINLINE size_t ApproximateProcessMemoryUsage( void )
+{
+ return 0;
+}
+
+#endif
+
+struct aligned_tmp_t
+{
+ // empty base class
+};
+
+/*
+This class used to be required if you wanted an object to be allocated with a specific
+alignment. ALIGN16 and ALIGN16_POST are not actually sufficient for this because they
+guarantee that the globals, statics, locals, and function parameters are appropriately
+aligned they do not affect memory allocation alignment.
+However this class is usually not needed because as of 2012 our policy is that our
+allocator should take care of this automatically. Any object whose size is a multiple
+of 16 will be 16-byte aligned. Existing uses of this class were not changed because
+the cost/benefit did not justify it.
+*/
+// 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:
+ /*
+ Note that this class does not overload operator new[] and delete[] which means that
+ classes that depend on this for alignment may end up misaligned if an array is
+ allocated. This problem is now mostly theoretical because this class is mostly
+ obsolete.
+ */
+ 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 );
+ }
+ }
+};
+
+
+#endif /* TIER0_MEMALLOC_H */
diff --git a/public/tier0/memdbgoff.h b/public/tier0/memdbgoff.h
new file mode 100644
index 0000000..1cd09da
--- /dev/null
+++ b/public/tier0/memdbgoff.h
@@ -0,0 +1,25 @@
+//========= Copyright 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/public/tier0/memdbgon.h b/public/tier0/memdbgon.h
new file mode 100644
index 0000000..9f022a0
--- /dev/null
+++ b/public/tier0/memdbgon.h
@@ -0,0 +1,318 @@
+//========= Copyright 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)
+#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 "basetypes.h"
+#ifdef _WIN32
+#include <tchar.h>
+#else
+#include <wchar.h>
+#endif
+#include <string.h>
+#include <malloc.h>
+#include "commonmacros.h"
+#include "memalloc.h"
+
+#if defined(USE_MEM_DEBUG)
+ #if defined( POSIX )
+
+ #define _NORMAL_BLOCK 1
+
+ #include <cstddef>
+ #include <glob.h>
+ #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
+ #ifdef OSX
+ void* operator new( size_t nSize, int blah, const char *pFileName, int nLine ) throw (std::bad_alloc);
+ void* operator new[]( size_t nSize, int blah, const char *pFileName, int nLine ) throw (std::bad_alloc);
+ #else
+ 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
+ #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)
+#define free(p) g_pMemAlloc->Free( p )
+#define _msize(p) g_pMemAlloc->GetSize( p )
+#define _expand(p, s) _expand_NoLongerSupported(p, s)
+#define _aligned_free( p ) MemAlloc_FreeAligned( p )
+
+// --------------------------------------------------------
+// Debug path
+#if defined(USE_MEM_DEBUG)
+
+#define malloc(s) g_pMemAlloc->Alloc( s, __FILE__, __LINE__)
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s, __FILE__, __LINE__ )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a, __FILE__, __LINE__ )
+
+#ifdef _malloc_dbg
+#undef _malloc_dbg
+#endif
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+
+#if !defined( POSIX )
+#if defined(__AFX_H__) && defined(DEBUG_NEW)
+ #define new DEBUG_NEW
+#else
+ #undef new
+ #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 *)g_pMemAlloc->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 *)g_pMemAlloc->Alloc(len * sizeof(wchar_t), pFileName, nLine)) != NULL)
+ {
+ return wcscpy( pMemory, pString );
+ }
+
+ return NULL;
+}
+
+#endif // DBMEM_DEFINED_STRDUP
+
+#else
+// --------------------------------------------------------
+// Release path
+
+#define malloc(s) g_pMemAlloc->Alloc( s )
+#define realloc(p, s) g_pMemAlloc->Realloc( p, s )
+#define _aligned_malloc( s, a ) MemAlloc_AllocAligned( s, a )
+
+#ifdef _malloc_dbg
+#undef _malloc_dbg
+#endif
+#define _malloc_dbg(s, t, f, l) WHYCALLINGTHISDIRECTLY(s)
+
+#undef new
+
+#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 *)g_pMemAlloc->Alloc(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 *)g_pMemAlloc->Alloc(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
+
+#else
+
+// Needed for MEM_ALLOC_CREDIT(), MemAlloc_Alloc(), etc.
+
+#include "memalloc.h"
+
+#if !defined( VALVE_ALLOCS_DEFINED )
+#define VALVE_ALLOCS_DEFINED
+
+#include "tier0/mem.h"
+
+inline void *valve_malloc_check_oom( size_t size )
+{
+ void *ptr = malloc( size );
+ if ( !ptr )
+ MemAllocOOMError( size );
+ return ptr;
+}
+
+inline void *valve_realloc_check_oom( void *ptr, size_t size )
+{
+ void *ret = realloc( ptr, size );
+ if ( !ret )
+ MemAllocOOMError( size );
+ return ret;
+}
+
+inline void *valve_calloc_check_oom( size_t num, size_t size )
+{
+ void *ptr = calloc( num, size );
+ if (!ptr)
+ MemAllocOOMError( num * size );
+ return ptr;
+}
+
+inline void *valve_memalign_check_oom( size_t alignment, size_t size )
+{
+ void *ptr = memalign( alignment, size );
+ if (!ptr)
+ MemAllocOOMError(size);
+ return ptr;
+}
+
+inline void *valve_aligned_malloc_check_oom( size_t size, size_t alignment )
+{
+ void *ptr = _aligned_malloc( size, alignment );
+ if (!ptr)
+ MemAllocOOMError( size );
+ return ptr;
+}
+
+
+#endif // VALVE_ALLOCS_DEFINED
+
+#define malloc valve_malloc_check_oom
+#define realloc valve_realloc_check_oom
+#define calloc valve_calloc_check_oom
+#define memalign valve_memalign_check_oom
+#define _aligned_malloc valve_aligned_malloc_check_oom
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
+
+#if defined( NO_MALLOC_OVERRIDE )
+
+#undef malloc
+#undef realloc
+#undef calloc
+#undef memalign
+#undef _aligned_malloc
+
+#endif // NO_MALLOC_OVERRIDE
diff --git a/public/tier0/memoverride.cpp b/public/tier0/memoverride.cpp
new file mode 100644
index 0000000..925f9d2
--- /dev/null
+++ b/public/tier0/memoverride.cpp
@@ -0,0 +1,1462 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Insert this file into all projects using the memory system
+// It will cause that project to use the shader memory allocator
+//
+// $NoKeywords: $
+//=============================================================================//
+
+
+#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
+
+#undef PROTECTED_THINGS_ENABLE // allow use of _vsnprintf
+
+#if defined( _WIN32 ) && !defined( _X360 )
+#define WIN_32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#ifdef _WIN32
+// ARG: crtdbg is necessary for certain definitions below,
+// but it also redefines malloc as a macro in release.
+// To disable this, we gotta define _DEBUG before including it.. BLEAH!
+#define _DEBUG 1
+#include "crtdbg.h"
+#ifdef NDEBUG
+#undef _DEBUG
+#endif
+// Turn this back off in release mode.
+#ifdef NDEBUG
+#undef _DEBUG
+#endif
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/memalloc.h"
+#include <string.h>
+#include <stdio.h>
+#include "memdbgoff.h"
+
+
+#if POSIX
+#define __cdecl
+#endif
+
+#if defined( _WIN32 ) && !defined( _X360 )
+const char *MakeModuleFileName()
+{
+ if ( g_pMemAlloc && g_pMemAlloc->IsDebugHeap() )
+ {
+ char *pszModuleName = (char *)HeapAlloc( GetProcessHeap(), 0, MAX_PATH ); // small leak, debug only
+
+ MEMORY_BASIC_INFORMATION mbi;
+ static int dummy;
+ VirtualQuery( &dummy, &mbi, sizeof(mbi) );
+
+ GetModuleFileName( reinterpret_cast<HMODULE>(mbi.AllocationBase), pszModuleName, MAX_PATH );
+ char *pDot = strrchr( pszModuleName, '.' );
+ if ( pDot )
+ {
+ char *pSlash = strrchr( pszModuleName, '\\' );
+ if ( pSlash )
+ {
+ pszModuleName = pSlash + 1;
+ *pDot = 0;
+ }
+ }
+
+ return pszModuleName;
+ }
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: helper class to detect when static construction has been done by the CRT
+//-----------------------------------------------------------------------------
+class CStaticConstructionCheck
+{
+public:
+ volatile bool m_bConstructed = true;
+};
+
+static CStaticConstructionCheck s_CheckStaticsConstructed;
+
+const char *GetModuleFileName()
+{
+#if !defined(_MSC_VER) || ( _MSC_VER >= 1900 ) // VC 2015 and above, with the UCRT, will crash if you use a static before it is constructed
+ if ( !s_CheckStaticsConstructed.m_bConstructed )
+ return nullptr;
+#endif
+
+ static const char *pszOwner = MakeModuleFileName();
+ return pszOwner;
+}
+
+
+static void *AllocUnattributed( size_t nSize )
+{
+ const char *pszOwner = GetModuleFileName();
+
+ if ( !pszOwner )
+ return g_pMemAlloc->Alloc(nSize);
+ else
+ return g_pMemAlloc->Alloc(nSize, pszOwner, 0);
+}
+
+static void *ReallocUnattributed( void *pMem, size_t nSize )
+{
+ const char *pszOwner = GetModuleFileName();
+
+ if ( !pszOwner )
+ return g_pMemAlloc->Realloc(pMem, nSize);
+ else
+ return g_pMemAlloc->Realloc(pMem, nSize, pszOwner, 0);
+}
+
+#else
+#define MakeModuleFileName() NULL
+inline void *AllocUnattributed( size_t nSize )
+{
+ return g_pMemAlloc->Alloc(nSize);
+}
+
+inline void *ReallocUnattributed( void *pMem, size_t nSize )
+{
+ return g_pMemAlloc->Realloc(pMem, nSize);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Standard functions in the CRT that we're going to override to call our allocator
+//-----------------------------------------------------------------------------
+#if defined(_WIN32) && !defined(_STATIC_LINKED)
+// this magic only works under win32
+// under linux this malloc() overrides the libc malloc() and so we
+// end up in a recursion (as g_pMemAlloc->Alloc() calls malloc)
+#if _MSC_VER >= 1900
+#define SUPPRESS_INVALID_PARAMETER_NO_INFO
+#define ALLOC_CALL __declspec(restrict)
+#define FREE_CALL
+#elif _MSC_VER >= 1400
+#define ALLOC_CALL _CRTNOALIAS _CRTRESTRICT
+#define FREE_CALL _CRTNOALIAS
+#else
+#define ALLOC_CALL
+#define FREE_CALL
+#endif
+
+extern "C"
+{
+
+ALLOC_CALL void *malloc( size_t nSize )
+{
+ return AllocUnattributed( nSize );
+}
+
+FREE_CALL void free( void *pMem )
+{
+ g_pMemAlloc->Free(pMem);
+}
+
+ALLOC_CALL void *realloc( void *pMem, size_t nSize )
+{
+ return ReallocUnattributed( pMem, nSize );
+}
+
+ALLOC_CALL void *calloc( size_t nCount, size_t nElementSize )
+{
+ void *pMem = AllocUnattributed( nElementSize * nCount );
+ memset(pMem, 0, nElementSize * nCount);
+ return pMem;
+}
+
+} // end extern "C"
+
+//-----------------------------------------------------------------------------
+// Non-standard MSVC functions that we're going to override to call our allocator
+//-----------------------------------------------------------------------------
+extern "C"
+{
+
+// 64-bit
+#ifdef _WIN64
+void* __cdecl _malloc_base( size_t nSize )
+{
+ return AllocUnattributed( nSize );
+}
+#else
+ALLOC_CALL void *_malloc_base( size_t nSize )
+{
+ return AllocUnattributed( nSize );
+}
+#endif
+
+ALLOC_CALL void *_calloc_base( size_t nCount, size_t nSize )
+{
+ void *pMem = AllocUnattributed( nSize*nCount );
+ memset(pMem, 0, nSize*nCount );
+ return pMem;
+}
+
+ALLOC_CALL void *_realloc_base( void *pMem, size_t nSize )
+{
+ return ReallocUnattributed( pMem, nSize );
+}
+
+ALLOC_CALL void *_recalloc_base( void *pMem, size_t nSize )
+{
+ void *pMemOut = ReallocUnattributed( pMem, nSize );
+ if ( !pMem )
+ {
+ memset( pMemOut, 0, nSize );
+ }
+ return pMemOut;
+}
+
+void _free_base( void *pMem )
+{
+ g_pMemAlloc->Free(pMem);
+}
+
+void *__cdecl _expand_base( void *pMem, size_t nNewSize, int nBlockUse )
+{
+ Assert( 0 );
+ return NULL;
+}
+
+// crt
+void * __cdecl _malloc_crt(size_t size)
+{
+ return AllocUnattributed( size );
+}
+
+void * __cdecl _calloc_crt(size_t count, size_t size)
+{
+ return _calloc_base( count, size );
+}
+
+void * __cdecl _realloc_crt(void *ptr, size_t size)
+{
+ return _realloc_base( ptr, size );
+}
+
+void * __cdecl _recalloc_crt(void *ptr, size_t count, size_t size)
+{
+ return _recalloc_base( ptr, size * count );
+}
+
+ALLOC_CALL void * __cdecl _recalloc ( void * memblock, size_t count, size_t size )
+{
+ void *pMem = ReallocUnattributed( memblock, size * count );
+ if ( !memblock )
+ {
+ memset( pMem, 0, size * count );
+ }
+ return pMem;
+}
+
+size_t _msize_base( void *pMem )
+{
+ return g_pMemAlloc->GetSize(pMem);
+}
+
+size_t _msize( void *pMem )
+{
+ return _msize_base(pMem);
+}
+
+size_t msize( void *pMem )
+{
+ return g_pMemAlloc->GetSize(pMem);
+}
+
+void *__cdecl _heap_alloc( size_t nSize )
+{
+ return AllocUnattributed( nSize );
+}
+
+void *__cdecl _nh_malloc( size_t nSize, int )
+{
+ return AllocUnattributed( nSize );
+}
+
+void *__cdecl _expand( void *pMem, size_t nSize )
+{
+ Assert( 0 );
+ return NULL;
+}
+
+unsigned int _amblksiz = 16; //BYTES_PER_PARA;
+
+#if _MSC_VER >= 1400
+HANDLE _crtheap = (HANDLE)1; // PatM Can't be 0 or CRT pukes
+int __active_heap = 1;
+#endif // _MSC_VER >= 1400
+
+size_t __cdecl _get_sbh_threshold( void )
+{
+ return 0;
+}
+
+int __cdecl _set_sbh_threshold( size_t )
+{
+ return 0;
+}
+
+int _heapchk()
+{
+ return g_pMemAlloc->heapchk();
+}
+
+int _heapmin()
+{
+ return 1;
+}
+
+int __cdecl _heapadd( void *, size_t )
+{
+ return 0;
+}
+
+int __cdecl _heapset( unsigned int )
+{
+ return 0;
+}
+
+size_t __cdecl _heapused( size_t *, size_t * )
+{
+ return 0;
+}
+
+#ifdef _WIN32
+int __cdecl _heapwalk( _HEAPINFO * )
+{
+ return 0;
+}
+#endif
+
+} // end extern "C"
+
+
+//-----------------------------------------------------------------------------
+// Debugging functions that we're going to override to call our allocator
+// NOTE: These have to be here for release + debug builds in case we
+// link to a debug static lib!!!
+//-----------------------------------------------------------------------------
+
+extern "C"
+{
+
+void *malloc_db( size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
+}
+
+void free_db( void *pMem, const char *pFileName, int nLine )
+{
+ g_pMemAlloc->Free(pMem, pFileName, nLine);
+}
+
+void *realloc_db( void *pMem, size_t nSize, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->Realloc(pMem, nSize, pFileName, nLine);
+}
+
+} // end extern "C"
+
+//-----------------------------------------------------------------------------
+// These methods are standard MSVC heap initialization + shutdown methods
+//-----------------------------------------------------------------------------
+extern "C"
+{
+
+#if !defined( _X360 )
+ int __cdecl _heap_init()
+ {
+ return g_pMemAlloc != NULL;
+ }
+
+ void __cdecl _heap_term()
+ {
+ }
+#endif
+
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Prevents us from using an inappropriate new or delete method,
+// ensures they are here even when linking against debug or release static libs
+//-----------------------------------------------------------------------------
+#ifndef NO_MEMOVERRIDE_NEW_DELETE
+#ifdef OSX
+void *__cdecl operator new( size_t nSize ) throw (std::bad_alloc)
+#else
+void *__cdecl operator new( size_t nSize )
+#endif
+{
+ return AllocUnattributed( nSize );
+}
+
+void *__cdecl operator new( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
+}
+
+#ifdef OSX
+void __cdecl operator delete( void *pMem ) throw()
+#else
+void __cdecl operator delete( void *pMem )
+#endif
+{
+ g_pMemAlloc->Free( pMem );
+}
+
+#ifdef OSX
+void operator delete(void*pMem, std::size_t)
+#else
+void operator delete(void*pMem, std::size_t) throw()
+#endif
+{
+ g_pMemAlloc->Free( pMem );
+}
+
+#ifdef OSX
+void *__cdecl operator new[]( size_t nSize ) throw (std::bad_alloc)
+#else
+void *__cdecl operator new[]( size_t nSize )
+#endif
+{
+ return AllocUnattributed( nSize );
+}
+
+void *__cdecl operator new[] ( size_t nSize, int nBlockUse, const char *pFileName, int nLine )
+{
+ return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
+}
+
+#ifdef OSX
+void __cdecl operator delete[]( void *pMem ) throw()
+#else
+void __cdecl operator delete[]( void *pMem )
+#endif
+{
+ g_pMemAlloc->Free( pMem );
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Override some debugging allocation methods in MSVC
+// NOTE: These have to be here for release + debug builds in case we
+// link to a debug static lib!!!
+//-----------------------------------------------------------------------------
+#ifndef _STATIC_LINKED
+#ifdef _WIN32
+
+// This here just hides the internal file names, etc of allocations
+// made in the c runtime library
+#define CRT_INTERNAL_FILE_NAME "C-runtime internal"
+
+class CAttibCRT
+{
+public:
+ CAttibCRT(int nBlockUse) : m_nBlockUse(nBlockUse)
+ {
+ if (m_nBlockUse == _CRT_BLOCK)
+ {
+ g_pMemAlloc->PushAllocDbgInfo(CRT_INTERNAL_FILE_NAME, 0);
+ }
+ }
+
+ ~CAttibCRT()
+ {
+ if (m_nBlockUse == _CRT_BLOCK)
+ {
+ g_pMemAlloc->PopAllocDbgInfo();
+ }
+ }
+
+private:
+ int m_nBlockUse;
+};
+
+
+#define AttribIfCrt() CAttibCRT _attrib(nBlockUse)
+#elif defined(POSIX)
+#define AttribIfCrt()
+#endif // _WIN32
+
+
+extern "C"
+{
+
+void *__cdecl _nh_malloc_dbg( size_t nSize, int nFlag, int nBlockUse,
+ const char *pFileName, int nLine )
+{
+ AttribIfCrt();
+ return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
+}
+
+void *__cdecl _malloc_dbg( size_t nSize, int nBlockUse,
+ const char *pFileName, int nLine )
+{
+ AttribIfCrt();
+ return g_pMemAlloc->Alloc(nSize, pFileName, nLine);
+}
+
+#if defined( _X360 )
+void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse,
+ const char * szFileName, int nLine, int * errno_tmp )
+{
+ return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine );
+}
+#endif
+
+void *__cdecl _calloc_dbg( size_t nNum, size_t nSize, int nBlockUse,
+ const char *pFileName, int nLine )
+{
+ AttribIfCrt();
+ void *pMem = g_pMemAlloc->Alloc(nSize * nNum, pFileName, nLine);
+ memset(pMem, 0, nSize * nNum);
+ return pMem;
+}
+
+void *__cdecl _calloc_dbg_impl( size_t nNum, size_t nSize, int nBlockUse,
+ const char * szFileName, int nLine, int * errno_tmp )
+{
+ return _calloc_dbg( nNum, nSize, nBlockUse, szFileName, nLine );
+}
+
+void *__cdecl _realloc_dbg( void *pMem, size_t nNewSize, int nBlockUse,
+ const char *pFileName, int nLine )
+{
+ AttribIfCrt();
+ return g_pMemAlloc->Realloc(pMem, nNewSize, pFileName, nLine);
+}
+
+void *__cdecl _expand_dbg( void *pMem, size_t nNewSize, int nBlockUse,
+ const char *pFileName, int nLine )
+{
+ Assert( 0 );
+ return NULL;
+}
+
+void __cdecl _free_dbg( void *pMem, int nBlockUse )
+{
+ AttribIfCrt();
+ g_pMemAlloc->Free(pMem);
+}
+
+size_t __cdecl _msize_dbg( void *pMem, int nBlockUse )
+{
+#ifdef _WIN32
+ return _msize(pMem);
+#elif POSIX
+ Assert( "_msize_dbg unsupported" );
+ return 0;
+#endif
+}
+
+
+#ifdef _WIN32
+
+#if defined(_DEBUG) && _MSC_VER >= 1300
+// aligned base
+ALLOC_CALL void *__cdecl _aligned_malloc_base( size_t size, size_t align )
+{
+ return MemAlloc_AllocAligned( size, align );
+}
+
+inline void *MemAlloc_Unalign( void *pMemBlock )
+{
+ unsigned *pAlloc = (unsigned *)pMemBlock;
+
+ // pAlloc points to the pointer to starting of the memory block
+ pAlloc = (unsigned *)(((size_t)pAlloc & ~(sizeof( void * ) - 1)) - sizeof( void * ));
+
+ // pAlloc is the pointer to the start of memory block
+ return *((unsigned **)pAlloc);
+}
+
+ALLOC_CALL void *__cdecl _aligned_realloc_base( void *ptr, size_t size, size_t align )
+{
+ if ( ptr && !size )
+ {
+ MemAlloc_FreeAligned( ptr );
+ return NULL;
+ }
+
+ void *pNew = MemAlloc_AllocAligned( size, align );
+ if ( ptr )
+ {
+ void *ptrUnaligned = MemAlloc_Unalign( ptr );
+ size_t oldSize = g_pMemAlloc->GetSize( ptrUnaligned );
+ size_t oldOffset = (uintp)ptr - (uintp)ptrUnaligned;
+ size_t copySize = oldSize - oldOffset;
+ if ( copySize > size )
+ copySize = size;
+ memcpy( pNew, ptr, copySize );
+ MemAlloc_FreeAligned( ptr );
+ }
+ return pNew;
+}
+
+ALLOC_CALL void *__cdecl _aligned_recalloc_base( void *ptr, size_t size, size_t align )
+{
+ Error( "Unsupported function\n" );
+ return NULL;
+}
+
+FREE_CALL void __cdecl _aligned_free_base( void *ptr )
+{
+ MemAlloc_FreeAligned( ptr );
+}
+
+// aligned
+ALLOC_CALL void * __cdecl _aligned_malloc( size_t size, size_t align )
+{
+ return _aligned_malloc_base(size, align);
+}
+
+ALLOC_CALL void *__cdecl _aligned_realloc(void *memblock, size_t size, size_t align)
+{
+ return _aligned_realloc_base(memblock, size, align);
+}
+
+ALLOC_CALL void * __cdecl _aligned_recalloc( void * memblock, size_t count, size_t size, size_t align )
+{
+ return _aligned_recalloc_base(memblock, count * size, align);
+}
+
+FREE_CALL void __cdecl _aligned_free( void *memblock )
+{
+ _aligned_free_base(memblock);
+}
+
+// aligned offset base
+ALLOC_CALL void * __cdecl _aligned_offset_malloc_base( size_t size, size_t align, size_t offset )
+{
+ Assert( IsPC() || 0 );
+ return NULL;
+}
+
+ALLOC_CALL void * __cdecl _aligned_offset_realloc_base( void * memblock, size_t size, size_t align, size_t offset)
+{
+ Assert( IsPC() || 0 );
+ return NULL;
+}
+
+ALLOC_CALL void * __cdecl _aligned_offset_recalloc_base( void * memblock, size_t size, size_t align, size_t offset)
+{
+ Assert( IsPC() || 0 );
+ return NULL;
+}
+
+// aligned offset
+ALLOC_CALL void *__cdecl _aligned_offset_malloc(size_t size, size_t align, size_t offset)
+{
+ return _aligned_offset_malloc_base( size, align, offset );
+}
+
+ALLOC_CALL void *__cdecl _aligned_offset_realloc(void *memblock, size_t size, size_t align, size_t offset)
+{
+ return _aligned_offset_realloc_base( memblock, size, align, offset );
+}
+
+ALLOC_CALL void * __cdecl _aligned_offset_recalloc( void * memblock, size_t count, size_t size, size_t align, size_t offset )
+{
+ return _aligned_offset_recalloc_base( memblock, count * size, align, offset );
+}
+
+#endif // _MSC_VER >= 1400
+
+#endif
+
+} // end extern "C"
+
+
+//-----------------------------------------------------------------------------
+// Override some the _CRT debugging allocation methods in MSVC
+//-----------------------------------------------------------------------------
+#ifdef _WIN32
+
+extern "C"
+{
+
+int _CrtDumpMemoryLeaks(void)
+{
+ return 0;
+}
+
+_CRT_DUMP_CLIENT _CrtSetDumpClient( _CRT_DUMP_CLIENT dumpClient )
+{
+ return NULL;
+}
+
+int _CrtSetDbgFlag( int nNewFlag )
+{
+ return g_pMemAlloc->CrtSetDbgFlag( nNewFlag );
+}
+
+// 64-bit port.
+#define AFNAME(var) __p_##var
+#define AFRET(var) &var
+#if defined(_crtDbgFlag)
+#undef _crtDbgFlag
+#endif
+#if defined(_crtBreakAlloc)
+#undef _crtBreakAlloc
+#endif
+
+int _crtDbgFlag = _CRTDBG_ALLOC_MEM_DF;
+int* AFNAME(_crtDbgFlag)(void)
+{
+ return AFRET(_crtDbgFlag);
+}
+
+long _crtBreakAlloc; /* Break on this allocation */
+long* AFNAME(_crtBreakAlloc) (void)
+{
+ return AFRET(_crtBreakAlloc);
+}
+
+void __cdecl _CrtSetDbgBlockType( void *pMem, int nBlockUse )
+{
+ DebuggerBreak();
+}
+
+_CRT_ALLOC_HOOK __cdecl _CrtSetAllocHook( _CRT_ALLOC_HOOK pfnNewHook )
+{
+ DebuggerBreak();
+ return NULL;
+}
+
+long __cdecl _CrtSetBreakAlloc( long lNewBreakAlloc )
+{
+ return g_pMemAlloc->CrtSetBreakAlloc( lNewBreakAlloc );
+}
+
+int __cdecl _CrtIsValidHeapPointer( const void *pMem )
+{
+ return g_pMemAlloc->CrtIsValidHeapPointer( pMem );
+}
+
+int __cdecl _CrtIsValidPointer( const void *pMem, unsigned int size, int access )
+{
+ return g_pMemAlloc->CrtIsValidPointer( pMem, size, access );
+}
+
+int __cdecl _CrtCheckMemory( void )
+{
+ // FIXME: Remove this when we re-implement the heap
+ return g_pMemAlloc->CrtCheckMemory( );
+}
+
+int __cdecl _CrtIsMemoryBlock( const void *pMem, unsigned int nSize,
+ long *plRequestNumber, char **ppFileName, int *pnLine )
+{
+ DebuggerBreak();
+ return 1;
+}
+
+int __cdecl _CrtMemDifference( _CrtMemState *pState, const _CrtMemState * oldState, const _CrtMemState * newState )
+{
+ DebuggerBreak();
+ return FALSE;
+}
+
+void __cdecl _CrtMemDumpStatistics( const _CrtMemState *pState )
+{
+ DebuggerBreak();
+}
+
+void __cdecl _CrtMemCheckpoint( _CrtMemState *pState )
+{
+ // FIXME: Remove this when we re-implement the heap
+ g_pMemAlloc->CrtMemCheckpoint( pState );
+}
+
+void __cdecl _CrtMemDumpAllObjectsSince( const _CrtMemState *pState )
+{
+ DebuggerBreak();
+}
+
+void __cdecl _CrtDoForAllClientObjects( void (*pfn)(void *, void *), void * pContext )
+{
+ DebuggerBreak();
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods in dbgrpt.cpp
+//-----------------------------------------------------------------------------
+long _crtAssertBusy = -1;
+
+int __cdecl _CrtSetReportMode( int nReportType, int nReportMode )
+{
+ return g_pMemAlloc->CrtSetReportMode( nReportType, nReportMode );
+}
+
+_HFILE __cdecl _CrtSetReportFile( int nRptType, _HFILE hFile )
+{
+ return (_HFILE)g_pMemAlloc->CrtSetReportFile( nRptType, hFile );
+}
+
+_CRT_REPORT_HOOK __cdecl _CrtSetReportHook( _CRT_REPORT_HOOK pfnNewHook )
+{
+ return (_CRT_REPORT_HOOK)g_pMemAlloc->CrtSetReportHook( pfnNewHook );
+}
+
+int __cdecl _CrtDbgReport( int nRptType, const char * szFile,
+ int nLine, const char * szModule, const char * szFormat, ... )
+{
+ static char output[1024];
+ va_list args;
+ if ( szFormat )
+ {
+ va_start( args, szFormat );
+ _vsnprintf( output, sizeof( output )-1, szFormat, args );
+ va_end( args );
+ }
+ else
+ {
+ output[0] = 0;
+ }
+
+ return g_pMemAlloc->CrtDbgReport( nRptType, szFile, nLine, szModule, output );
+}
+
+#if _MSC_VER >= 1400
+
+// Configure VS so that it will record crash dumps on pure-call violations
+// and invalid parameter handlers.
+// If you manage to call a pure-virtual function (easily done if you indirectly
+// call a pure-virtual function from the base-class constructor or destructor)
+// or if you invoke the invalid parameter handler (printf(NULL); is one way)
+// then no crash dump will be created.
+// This crash redirects the handlers for these two events so that crash dumps
+// are created.
+//
+// The ErrorHandlerRegistrar object must be in memoverride.cpp so that it will
+// be placed in every DLL and EXE. This is required because each DLL and EXE
+// gets its own copy of the C run-time and these overrides are set on a per-CRT
+// basis.
+
+/*
+// This sample code will cause pure-call and invalid_parameter violations and
+// was used for testing:
+class Base
+{
+public:
+ virtual void PureFunction() = 0;
+
+ Base()
+ {
+ NonPureFunction();
+ }
+
+ void NonPureFunction()
+ {
+ PureFunction();
+ }
+};
+
+class Derived : public Base
+{
+public:
+ void PureFunction() OVERRIDE
+ {
+ }
+};
+
+void PureCallViolation()
+{
+ Derived derived;
+}
+
+void InvalidParameterViolation()
+{
+ printf( NULL );
+}
+*/
+
+#include <stdlib.h>
+#include "minidump.h"
+
+// Disable compiler optimizations. If we don't do this then VC++ generates code
+// that confuses the Visual Studio debugger and causes it to display completely
+// random call stacks. That makes the minidumps excruciatingly hard to understand.
+#pragma optimize("", off)
+
+// Write a minidump file, unless running under the debugger in which case break
+// into the debugger.
+// The "int dummy" parameter is so that the callers can be unique so that the
+// linker won't use its /opt:icf optimization to collapse them together. This
+// makes reading the call stack easier.
+void __cdecl WriteMiniDumpOrBreak( int dummy, const char *pchName )
+{
+ if ( Plat_IsInDebugSession() )
+ {
+ __debugbreak();
+ // Continue at your peril...
+ }
+ else
+ {
+ WriteMiniDump( pchName );
+ // Call Plat_ExitProcess so we don't continue in a bad state.
+ TerminateProcess(GetCurrentProcess(), 0);
+ }
+}
+
+void __cdecl VPureCall()
+{
+ WriteMiniDumpOrBreak( 0, "PureClass" );
+}
+
+void VInvalidParameterHandler(const wchar_t* expression,
+ const wchar_t* function,
+ const wchar_t* file,
+ unsigned int line,
+ uintptr_t pReserved)
+{
+ WriteMiniDumpOrBreak( 1, "InvalidParameterHandler" );
+}
+
+// Restore compiler optimizations.
+#pragma optimize("", on)
+
+// Helper class for registering error callbacks. See above for details.
+class ErrorHandlerRegistrar
+{
+public:
+ ErrorHandlerRegistrar();
+} s_ErrorHandlerRegistration;
+
+ErrorHandlerRegistrar::ErrorHandlerRegistrar()
+{
+ _set_purecall_handler( VPureCall );
+ _set_invalid_parameter_handler( VInvalidParameterHandler );
+}
+
+#if defined( _DEBUG )
+
+// wrapper which passes no debug info; not available in debug
+#ifndef SUPPRESS_INVALID_PARAMETER_NO_INFO
+void __cdecl _invalid_parameter_noinfo(void)
+{
+ Assert(0);
+}
+#endif
+
+#endif /* defined( _DEBUG ) */
+
+#if defined( _DEBUG ) || defined( USE_MEM_DEBUG )
+
+int __cdecl __crtMessageWindowW( int nRptType, const wchar_t * szFile, const wchar_t * szLine,
+ const wchar_t * szModule, const wchar_t * szUserMessage )
+{
+ Assert(0);
+ return 0;
+}
+
+int __cdecl _CrtDbgReportV( int nRptType, const wchar_t *szFile, int nLine,
+ const wchar_t *szModule, const wchar_t *szFormat, va_list arglist )
+{
+ Assert(0);
+ return 0;
+}
+
+int __cdecl _CrtDbgReportW( int nRptType, const wchar_t *szFile, int nLine,
+ const wchar_t *szModule, const wchar_t *szFormat, ...)
+{
+ Assert(0);
+ return 0;
+}
+
+#if _MSC_VER >= 1900
+int __cdecl _VCrtDbgReportA( int nRptType, void* ReturnAddress, const char * szFile, int nLine,
+ const char * szModule, const char * szFormat, va_list arglist )
+{
+ Assert(0);
+ return 0;
+}
+#else
+int __cdecl _VCrtDbgReportA( int nRptType, const wchar_t * szFile, int nLine,
+ const wchar_t * szModule, const wchar_t * szFormat, va_list arglist )
+{
+ Assert( 0 );
+ return 0;
+}
+#endif
+
+int __cdecl _CrtSetReportHook2( int mode, _CRT_REPORT_HOOK pfnNewHook )
+{
+ _CrtSetReportHook( pfnNewHook );
+ return 0;
+}
+
+
+#endif /* defined( _DEBUG ) || defined( USE_MEM_DEBUG ) */
+
+extern "C" int __crtDebugCheckCount = FALSE;
+
+extern "C" int __cdecl _CrtSetCheckCount( int fCheckCount )
+{
+ int oldCheckCount = __crtDebugCheckCount;
+ return oldCheckCount;
+}
+
+extern "C" int __cdecl _CrtGetCheckCount( void )
+{
+ return __crtDebugCheckCount;
+}
+
+// aligned offset debug
+extern "C" void * __cdecl _aligned_offset_recalloc_dbg( void * memblock, size_t count, size_t size, size_t align, size_t offset, const char * f_name, int line_n )
+{
+ Assert( IsPC() || 0 );
+ void *pMem = ReallocUnattributed( memblock, size * count );
+ if ( !memblock )
+ {
+ memset( pMem, 0, size * count );
+ }
+ return pMem;
+}
+
+extern "C" void * __cdecl _aligned_recalloc_dbg( void *memblock, size_t count, size_t size, size_t align, const char * f_name, int line_n )
+{
+ return _aligned_offset_recalloc_dbg(memblock, count, size, align, 0, f_name, line_n);
+}
+
+extern "C" void * __cdecl _recalloc_dbg ( void * memblock, size_t count, size_t size, int nBlockUse, const char * szFileName, int nLine )
+{
+ return _aligned_offset_recalloc_dbg(memblock, count, size, 0, 0, szFileName, nLine);
+}
+
+_CRT_REPORT_HOOK __cdecl _CrtGetReportHook( void )
+{
+ return NULL;
+}
+
+#endif
+int __cdecl _CrtReportBlockType(const void * pUserData)
+{
+ return 0;
+}
+
+
+} // end extern "C"
+#endif // _WIN32
+
+// Most files include this file, so when it's used it adds an extra .ValveDbg section,
+// to help identify debug binaries.
+#ifdef _WIN32
+ #ifndef NDEBUG // _DEBUG
+ #pragma data_seg("ValveDBG")
+ volatile const char* DBG = "*** DEBUG STUB ***";
+ #endif
+#endif
+
+#endif
+
+// Extras added prevent dbgheap.obj from being included - DAL
+#ifdef _WIN32
+
+extern "C"
+{
+size_t __crtDebugFillThreshold = 0;
+
+extern "C" void * __cdecl _heap_alloc_base (size_t size) {
+ assert(0);
+ return NULL;
+}
+
+
+void * __cdecl _heap_alloc_dbg( size_t nSize, int nBlockUse, const char * szFileName, int nLine)
+{
+ return _heap_alloc(nSize);
+}
+
+// 64-bit
+#ifdef _WIN64
+static void * __cdecl realloc_help( void * pUserData, size_t * pnNewSize, int nBlockUse,const char * szFileName,
+ int nLine, int fRealloc )
+{
+ assert(0); // Shouldn't be needed
+ return NULL;
+}
+#else
+static void * __cdecl realloc_help( void * pUserData, size_t nNewSize, int nBlockUse, const char * szFileName,
+ int nLine, int fRealloc)
+{
+ assert(0); // Shouldn't be needed
+ return NULL;
+}
+#endif
+
+void __cdecl _free_nolock( void * pUserData)
+{
+ // I don't think the second param is used in memoverride
+ _free_dbg(pUserData, 0);
+}
+
+void __cdecl _free_dbg_nolock( void * pUserData, int nBlockUse)
+{
+ _free_dbg(pUserData, 0);
+}
+
+_CRT_ALLOC_HOOK __cdecl _CrtGetAllocHook ( void)
+{
+ assert(0);
+ return NULL;
+}
+
+static int __cdecl CheckBytes( unsigned char * pb, unsigned char bCheck, size_t nSize)
+{
+ int bOkay = TRUE;
+ return bOkay;
+}
+
+
+_CRT_DUMP_CLIENT __cdecl _CrtGetDumpClient ( void)
+{
+ assert(0);
+ return NULL;
+}
+
+#if _MSC_VER >= 1400
+static void __cdecl _printMemBlockData( _locale_t plocinfo, _CrtMemBlockHeader * pHead)
+{
+}
+
+static void __cdecl _CrtMemDumpAllObjectsSince_stat( const _CrtMemState * state, _locale_t plocinfo)
+{
+}
+#endif
+void * __cdecl _aligned_malloc_dbg( size_t size, size_t align, const char * f_name, int line_n)
+{
+ return _aligned_malloc(size, align);
+}
+
+void * __cdecl _aligned_realloc_dbg( void *memblock, size_t size, size_t align,
+ const char * f_name, int line_n)
+{
+ return _aligned_realloc(memblock, size, align);
+}
+
+void * __cdecl _aligned_offset_malloc_dbg( size_t size, size_t align, size_t offset,
+ const char * f_name, int line_n)
+{
+ return _aligned_offset_malloc(size, align, offset);
+}
+
+void * __cdecl _aligned_offset_realloc_dbg( void * memblock, size_t size, size_t align,
+ size_t offset, const char * f_name, int line_n)
+{
+ return _aligned_offset_realloc(memblock, size, align, offset);
+}
+
+void __cdecl _aligned_free_dbg( void * memblock)
+{
+ _aligned_free(memblock);
+}
+
+#if _MSC_VER < 1900
+size_t __cdecl _CrtSetDebugFillThreshold( size_t _NewDebugFillThreshold)
+{
+ assert(0);
+ return 0;
+}
+
+//===========================================
+// NEW!!! 64-bit
+
+char * __cdecl _strdup ( const char * string )
+{
+ int nSize = (int)strlen(string) + 1;
+ // Check for integer underflow.
+ if ( nSize <= 0 )
+ return NULL;
+ char *pCopy = (char*)AllocUnattributed( nSize );
+ if ( pCopy )
+ memcpy( pCopy, string, nSize );
+ return pCopy;
+}
+#endif
+
+#if 0
+_TSCHAR * __cdecl _tfullpath_dbg ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen, int nBlockUse, const char * szFileName, int nLine )
+{
+ Assert(0);
+ return NULL;
+}
+
+_TSCHAR * __cdecl _tfullpath ( _TSCHAR *UserBuf, const _TSCHAR *path, size_t maxlen )
+{
+ Assert(0);
+ return NULL;
+}
+
+_TSCHAR * __cdecl _tgetdcwd_lk_dbg ( int drive, _TSCHAR *pnbuf, int maxlen, int nBlockUse, const char * szFileName, int nLine )
+{
+ Assert(0);
+ return NULL;
+}
+
+_TSCHAR * __cdecl _tgetdcwd_nolock ( int drive, _TSCHAR *pnbuf, int maxlen )
+{
+ Assert(0);
+ return NULL;
+}
+
+errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname, int nBlockUse, const char * szFileName, int nLine )
+{
+ Assert(0);
+ return 0;
+}
+
+errno_t __cdecl _tdupenv_s_helper ( _TSCHAR **pBuffer, size_t *pBufferSizeInTChars, const _TSCHAR *varname )
+{
+ Assert(0);
+ return 0;
+}
+
+_TSCHAR * __cdecl _ttempnam_dbg ( const _TSCHAR *dir, const _TSCHAR *pfx, int nBlockUse, const char * szFileName, int nLine )
+{
+ Assert(0);
+ return 0;
+}
+
+_TSCHAR * __cdecl _ttempnam ( const _TSCHAR *dir, const _TSCHAR *pfx )
+{
+ Assert(0);
+ return 0;
+}
+
+wchar_t * __cdecl _wcsdup_dbg ( const wchar_t * string, int nBlockUse, const char * szFileName, int nLine )
+{
+ Assert(0);
+ return 0;
+}
+
+wchar_t * __cdecl _wcsdup ( const wchar_t * string )
+{
+ Assert(0);
+ return 0;
+}
+#endif
+} // end extern "C"
+
+#if _MSC_VER >= 1400
+
+//-----------------------------------------------------------------------------
+// XBox Memory Allocator Override
+//-----------------------------------------------------------------------------
+#if defined( _X360 )
+#if defined( _DEBUG ) || defined( USE_MEM_DEBUG )
+#include "utlmap.h"
+
+MEMALLOC_DEFINE_EXTERNAL_TRACKING( XMem );
+
+CThreadFastMutex g_XMemAllocMutex;
+
+void XMemAlloc_RegisterAllocation( void *p, DWORD dwAllocAttributes )
+{
+ if ( !g_pMemAlloc )
+ {
+ // core xallocs cannot be journaled until system is ready
+ return;
+ }
+
+ AUTO_LOCK_FM( g_XMemAllocMutex );
+ int size = XMemSize( p, dwAllocAttributes );
+ MemAlloc_RegisterExternalAllocation( XMem, p, size );
+}
+
+void XMemAlloc_RegisterDeallocation( void *p, DWORD dwAllocAttributes )
+{
+ if ( !g_pMemAlloc )
+ {
+ // core xallocs cannot be journaled until system is ready
+ return;
+ }
+
+ AUTO_LOCK_FM( g_XMemAllocMutex );
+ int size = XMemSize( p, dwAllocAttributes );
+ MemAlloc_RegisterExternalDeallocation( XMem, p, size );
+}
+
+#else
+
+#define XMemAlloc_RegisterAllocation( p, a ) ((void)0)
+#define XMemAlloc_RegisterDeallocation( p, a ) ((void)0)
+
+#endif
+
+//-----------------------------------------------------------------------------
+// XMemAlloc
+//
+// XBox Memory Allocator Override
+//-----------------------------------------------------------------------------
+LPVOID WINAPI XMemAlloc( SIZE_T dwSize, DWORD dwAllocAttributes )
+{
+ LPVOID ptr;
+ XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
+ bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
+
+ if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
+ {
+ MEM_ALLOC_CREDIT();
+ switch ( pAttribs->dwAlignment )
+ {
+ case XALLOC_ALIGNMENT_4:
+ ptr = g_pMemAlloc->Alloc( dwSize );
+ break;
+ case XALLOC_ALIGNMENT_8:
+ ptr = MemAlloc_AllocAligned( dwSize, 8 );
+ break;
+ case XALLOC_ALIGNMENT_DEFAULT:
+ case XALLOC_ALIGNMENT_16:
+ default:
+ ptr = MemAlloc_AllocAligned( dwSize, 16 );
+ break;
+ }
+ if ( pAttribs->dwZeroInitialize != 0 )
+ {
+ memset( ptr, 0, XMemSize( ptr, dwAllocAttributes ) );
+ }
+ return ptr;
+ }
+
+ ptr = XMemAllocDefault( dwSize, dwAllocAttributes );
+ if ( ptr )
+ {
+ XMemAlloc_RegisterAllocation( ptr, dwAllocAttributes );
+ }
+
+ return ptr;
+}
+
+//-----------------------------------------------------------------------------
+// XMemFree
+//
+// XBox Memory Allocator Override
+//-----------------------------------------------------------------------------
+VOID WINAPI XMemFree( PVOID pAddress, DWORD dwAllocAttributes )
+{
+ if ( !pAddress )
+ {
+ return;
+ }
+
+ XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
+ bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
+
+ if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
+ {
+ switch ( pAttribs->dwAlignment )
+ {
+ case XALLOC_ALIGNMENT_4:
+ return g_pMemAlloc->Free( pAddress );
+ default:
+ return MemAlloc_FreeAligned( pAddress );
+ }
+ return;
+ }
+
+ XMemAlloc_RegisterDeallocation( pAddress, dwAllocAttributes );
+
+ XMemFreeDefault( pAddress, dwAllocAttributes );
+}
+
+//-----------------------------------------------------------------------------
+// XMemSize
+//
+// XBox Memory Allocator Override
+//-----------------------------------------------------------------------------
+SIZE_T WINAPI XMemSize( PVOID pAddress, DWORD dwAllocAttributes )
+{
+ XALLOC_ATTRIBUTES *pAttribs = (XALLOC_ATTRIBUTES *)&dwAllocAttributes;
+ bool bPhysical = ( pAttribs->dwMemoryType == XALLOC_MEMTYPE_PHYSICAL );
+
+ if ( !bPhysical && !pAttribs->dwHeapTracksAttributes && pAttribs->dwAllocatorId != eXALLOCAllocatorId_XUI )
+ {
+ switch ( pAttribs->dwAlignment )
+ {
+ case XALLOC_ALIGNMENT_4:
+ return g_pMemAlloc->GetSize( pAddress );
+ default:
+ return MemAlloc_GetSizeAligned( pAddress );
+ }
+ }
+
+ return XMemSizeDefault( pAddress, dwAllocAttributes );
+}
+#endif
+
+#pragma warning(push)
+#pragma warning(disable: 4483)
+#if _MSC_FULL_VER >= 140050415
+#define _NATIVE_STARTUP_NAMESPACE __identifier("<CrtImplementationDetails>")
+#else /* _MSC_FULL_VER >= 140050415 */
+#define _NATIVE_STARTUP_NAMESPACE __CrtImplementationDetails
+#endif /* _MSC_FULL_VER >= 140050415 */
+
+namespace _NATIVE_STARTUP_NAMESPACE
+{
+ class NativeDll
+ {
+ private:
+ static const unsigned int ProcessDetach = 0;
+ static const unsigned int ProcessAttach = 1;
+ static const unsigned int ThreadAttach = 2;
+ static const unsigned int ThreadDetach = 3;
+ static const unsigned int ProcessVerifier = 4;
+
+ public:
+
+ inline static bool IsInDllMain()
+ {
+ return false;
+ }
+
+ inline static bool IsInProcessAttach()
+ {
+ return false;
+ }
+
+ inline static bool IsInProcessDetach()
+ {
+ return false;
+ }
+
+ inline static bool IsInVcclrit()
+ {
+ return false;
+ }
+
+ inline static bool IsSafeForManagedCode()
+ {
+ if (!IsInDllMain())
+ {
+ return true;
+ }
+
+ if (IsInVcclrit())
+ {
+ return true;
+ }
+
+ return !IsInProcessAttach() && !IsInProcessDetach();
+ }
+ };
+}
+#pragma warning(pop)
+
+#endif // _MSC_VER >= 1400
+
+#endif // !STEAM && !NO_MALLOC_OVERRIDE
+
+#endif // _WIN32
diff --git a/public/tier0/minidump.h b/public/tier0/minidump.h
new file mode 100644
index 0000000..e650725
--- /dev/null
+++ b/public/tier0/minidump.h
@@ -0,0 +1,104 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#ifndef MINIDUMP_H
+#define MINIDUMP_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+
+// Set prefix to use for minidump files. If you don't set one, it is defaulted for you,
+// using the current module name
+PLATFORM_INTERFACE void SetMinidumpFilenamePrefix( const char *pszPrefix );
+
+// Set comment to put into minidump file upon next call of WriteMiniDump. (Most common use is the assert text.)
+PLATFORM_INTERFACE void SetMinidumpComment( const char *pszComment );
+
+// writes out a minidump of the current stack trace with a unique filename
+PLATFORM_INTERFACE void WriteMiniDump( const char *pszFilenameSuffix = NULL );
+
+typedef void (*FnWMain)( int , tchar *[] );
+typedef void (*FnVoidPtrFn)( void * );
+
+#if defined(_WIN32) && !defined(_X360)
+
+// 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
+typedef void (*FnWMain)( int , tchar *[] );
+typedef int (*FnWMainIntRet)( int , tchar *[] );
+typedef void (*FnVoidPtrFn)( void * );
+
+enum ECatchAndWriteMinidumpAction
+{
+ k_ECatchAndWriteMiniDumpAbort = 0,
+ k_ECatchAndWriteMiniDumpReThrow = 1,
+ k_ECatchAndWriteMiniDumpIgnore = 2,
+};
+
+PLATFORM_INTERFACE void CatchAndWriteMiniDump( FnWMain pfn, int argc, tchar *argv[] ); // action = Abort
+PLATFORM_INTERFACE void CatchAndWriteMiniDumpForVoidPtrFn( FnVoidPtrFn pfn, void *pv, bool bExitQuietly ); // action = abort if bExitQuietly, Rethrow otherwise
+
+PLATFORM_INTERFACE void CatchAndWriteMiniDumpEx( FnWMain pfn, int argc, tchar *argv[], ECatchAndWriteMinidumpAction eAction );
+PLATFORM_INTERFACE int CatchAndWriteMiniDumpExReturnsInt( FnWMainIntRet pfn, int argc, tchar *argv[], ECatchAndWriteMinidumpAction eAction );
+PLATFORM_INTERFACE void CatchAndWriteMiniDumpExForVoidPtrFn( FnVoidPtrFn pfn, void *pv, ECatchAndWriteMinidumpAction eAction );
+
+// Let's not include this. We'll use forwards instead.
+//#include <dbghelp.h>
+struct _EXCEPTION_POINTERS;
+
+// 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, _EXCEPTION_POINTERS * pExceptionInfo, const char *pszFilenameSuffix );
+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.
+//
+PLATFORM_INTERFACE bool WriteMiniDumpUsingExceptionInfo(
+ unsigned int uStructuredExceptionCode,
+ _EXCEPTION_POINTERS * pExceptionInfo,
+ int /* MINIDUMP_TYPE */ minidumpType,
+ const char *pszFilenameSuffix = NULL,
+ tchar *ptchMinidumpFileNameBuffer = NULL
+ );
+
+// Call this to enable a handler for unhandled exceptions.
+PLATFORM_INTERFACE void MinidumpSetUnhandledExceptionFunction( FnMiniDump pfn );
+
+// Call this to prevent crashes in kernel callbacks such as window procs from
+// being silently swallowed. We should always call this at startup.
+PLATFORM_INTERFACE void EnableCrashingOnCrashes();
+
+#endif // defined(_WIN32) && !defined(_X360)
+
+//
+// Minidump User Stream Info Comments.
+//
+// There currently is a single header string, and an array of 64 comment strings.
+// MinidumpUserStreamInfoSetHeader() will set the single header string.
+// MinidumpUserStreamInfoAppend() will round robin through and array and set the comment strings, overwriting old.
+PLATFORM_INTERFACE void MinidumpUserStreamInfoSetHeader( const char *pFormat, ... );
+PLATFORM_INTERFACE void MinidumpUserStreamInfoAppend( const char *pFormat, ... );
+
+// Retrieve the StreamInfo strings.
+// Index 0: header string
+// Index 1..: comment string
+// Returns NULL when you've reached the end of the comment string array
+// Empty strings ("\0") can be returned if comment hasn't been set
+PLATFORM_INTERFACE const char *MinidumpUserStreamInfoGet( int Index );
+
+#endif // MINIDUMP_H
+
diff --git a/public/tier0/platform.h b/public/tier0/platform.h
new file mode 100644
index 0000000..6387139
--- /dev/null
+++ b/public/tier0/platform.h
@@ -0,0 +1,1691 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//===========================================================================//
+
+#ifndef PLATFORM_H
+#define PLATFORM_H
+
+#if defined(__x86_64__) || defined(_WIN64)
+#define PLATFORM_64BITS 1
+#endif
+
+#if defined(__GCC__) || defined(__GNUC__)
+#define COMPILER_GCC 1
+#endif
+
+#ifdef __clang__
+#define COMPILER_CLANG 1
+#endif
+
+#if defined( _X360 )
+ #define NO_STEAM
+ #define NO_VOICE
+ // 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 <xtl.h>
+ #include <xaudio2.h>
+ #include <xbdm.h>
+#include <Xgraphics.h>
+ #include <xui.h>
+ #include <pmcpbsetup.h>
+#include <XMAHardwareAbstraction.h>
+ #undef _XBOX
+#endif
+
+#define __STDC_LIMIT_MACROS
+#include <stdint.h>
+
+#include "wchartypes.h"
+#include "basetypes.h"
+#include "tier0/valve_off.h"
+
+#ifdef _DEBUG
+#if !defined( PLAT_COMPILE_TIME_ASSERT )
+#define PLAT_COMPILE_TIME_ASSERT( pred ) switch(0){case 0:case pred:;}
+#endif
+#else
+#if !defined( PLAT_COMPILE_TIME_ASSERT )
+#define PLAT_COMPILE_TIME_ASSERT( pred )
+#endif
+#endif
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+// feature enables
+#define NEW_SOFTWARE_LIGHTING
+
+#ifdef POSIX
+// need this for _alloca
+#include <alloca.h>
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#endif
+
+#include <malloc.h>
+#include <new>
+
+// need this for memset
+#include <string.h>
+
+#include "tier0/valve_minmax_on.h" // GCC 4.2.2 headers screw up our min/max defs.
+
+#ifdef _RETAIL
+#define IsRetail() true
+#else
+#define IsRetail() false
+#endif
+
+#ifdef _DEBUG
+#define IsRelease() false
+#define IsDebug() true
+#else
+#define IsRelease() true
+#define IsDebug() false
+#endif
+
+// Deprecating, infavor of IsX360() which will revert to IsXbox()
+// after confidence of xbox 1 code flush
+#define IsXbox() false
+
+#ifdef _WIN32
+ #define IsLinux() false
+ #define IsOSX() false
+ #define IsPosix() false
+ #define PLATFORM_WINDOWS 1 // Windows PC or Xbox 360
+ #ifndef _X360
+ #define IsWindows() true
+ #define IsPC() true
+ #define IsConsole() false
+ #define IsX360() false
+ #define IsPS3() false
+ #define IS_WINDOWS_PC
+ #define PLATFORM_WINDOWS_PC 1 // Windows PC
+ #ifdef _WIN64
+ #define IsPlatformWindowsPC64() true
+ #define IsPlatformWindowsPC32() false
+ #define PLATFORM_WINDOWS_PC64 1
+ #else
+ #define IsPlatformWindowsPC64() false
+ #define IsPlatformWindowsPC32() true
+ #define PLATFORM_WINDOWS_PC32 1
+ #endif
+ #else
+ #define PLATFORM_X360 1
+ #ifndef _CONSOLE
+ #define _CONSOLE
+ #endif
+ #define IsWindows() false
+ #define IsPC() false
+ #define IsConsole() true
+ #define IsX360() true
+ #define IsPS3() false
+ #endif
+ // Adding IsPlatformOpenGL() to help fix a bunch of code that was using IsPosix() to infer if the DX->GL translation layer was being used.
+ #if defined( DX_TO_GL_ABSTRACTION )
+ #define IsPlatformOpenGL() true
+ #else
+ #define IsPlatformOpenGL() false
+ #endif
+#elif defined(POSIX)
+ #define IsPC() true
+ #define IsWindows() false
+ #define IsConsole() false
+ #define IsX360() false
+ #define IsPS3() false
+ #if defined( LINUX )
+ #define IsLinux() true
+ #else
+ #define IsLinux() false
+ #endif
+
+ #if defined( OSX )
+ #define IsOSX() true
+ #else
+ #define IsOSX() false
+ #endif
+
+ #define IsPosix() true
+ #define IsPlatformOpenGL() true
+#else
+ #error
+#endif
+
+typedef unsigned char uint8;
+typedef signed char int8;
+
+#if defined( _WIN32 )
+
+ typedef __int16 int16;
+ typedef unsigned __int16 uint16;
+ typedef __int32 int32;
+ typedef unsigned __int32 uint32;
+ typedef __int64 int64;
+ typedef unsigned __int64 uint64;
+
+ #ifdef PLATFORM_64BITS
+ typedef __int64 intp; // intp is an integer that can accomodate a pointer
+ typedef unsigned __int64 uintp; // (ie, sizeof(intp) >= sizeof(int) && sizeof(intp) >= sizeof(void *)
+ #else
+ typedef __int32 intp;
+ typedef unsigned __int32 uintp;
+ #endif
+
+ #if defined( _X360 )
+ #ifdef __m128
+ #undef __m128
+ #endif
+ #define __m128 __vector4
+ #endif
+
+ // Use this to specify that a function is an override of a virtual function.
+ // This lets the compiler catch cases where you meant to override a virtual
+ // function but you accidentally changed the function signature and created
+ // an overloaded function. Usage in function declarations is like this:
+ // int GetData() const OVERRIDE;
+ #define OVERRIDE override
+
+#else // _WIN32
+
+ 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;
+
+ // Avoid redefinition warnings if a previous header defines this.
+ #undef OVERRIDE
+ #if __cplusplus >= 201103L
+ #define OVERRIDE override
+ #if defined(__clang__)
+ // warning: 'override' keyword is a C++11 extension [-Wc++11-extensions]
+ // Disabling this warning is less intrusive than enabling C++11 extensions
+ #pragma GCC diagnostic ignored "-Wc++11-extensions"
+ #endif
+ #else
+ #define OVERRIDE
+ #endif
+
+#endif // else _WIN32
+
+//-----------------------------------------------------------------------------
+// Set up platform type defines.
+//-----------------------------------------------------------------------------
+#if defined( PLATFORM_X360 ) || defined( _PS3 )
+ #if !defined( _GAMECONSOLE )
+ #define _GAMECONSOLE
+ #endif
+ #define IsPC() false
+ #define IsGameConsole() true
+#else
+ #define IsPC() true
+ #define IsGameConsole() false
+#endif
+
+#ifdef PLATFORM_64BITS
+ #define IsPlatform64Bits() true
+#else
+ #define IsPlatform64Bits() false
+#endif
+
+// From steam/steamtypes.h
+// RTime32
+// We use this 32 bit time representing real world time.
+// It offers 1 second resolution beginning on January 1, 1970 (Unix time)
+typedef uint32 RTime32;
+
+typedef float float32;
+typedef double float64;
+
+// for when we don't care about how many bits we use
+typedef unsigned int uint;
+
+#ifdef _MSC_VER
+#pragma once
+// Ensure that everybody has the right compiler version installed. The version
+// number can be obtained by looking at the compiler output when you type 'cl'
+// and removing the last two digits and the periods: 16.00.40219.01 becomes 160040219
+#if _MSC_FULL_VER > 180000000
+ #if _MSC_FULL_VER < 180030723
+ #error You must install VS 2013 Update 3
+ #endif
+#elif _MSC_FULL_VER > 160000000
+ #if _MSC_FULL_VER < 160040219
+ #error You must install VS 2010 SP1
+ #endif
+#else
+ #if _MSC_FULL_VER < 140050727
+ #error You must install VS 2005 SP1
+ #endif
+#endif
+#endif
+
+// 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
+#ifdef _MSC_VER
+#define SINGLE_INHERITANCE __single_inheritance
+#define MULTIPLE_INHERITANCE __multiple_inheritance
+#else
+#define SINGLE_INHERITANCE
+#define MULTIPLE_INHERITANCE
+#endif
+
+#ifdef _MSC_VER
+#define NO_VTABLE __declspec( novtable )
+#else
+#define NO_VTABLE
+#endif
+
+#ifdef _MSC_VER
+ // This indicates that a function never returns, which helps with
+ // generating accurate compiler warnings
+ #define NORETURN __declspec( noreturn )
+#else
+ #define NORETURN
+#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 _X360
+#define abstract_class class
+#else
+#define abstract_class class NO_VTABLE
+#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
+
+/*
+FIXME: Enable this when we no longer fear change =)
+
+// need these for the limits
+#include <limits.h>
+#include <float.h>
+
+// Maximum and minimum representable values
+#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
+
+#ifndef UINT_MIN
+#define UINT_MIN UINT32_MIN
+#endif
+
+#define FLOAT32_MAX FLT_MAX
+#define FLOAT64_MAX DBL_MAX
+
+#define FLOAT32_MIN FLT_MIN
+#define FLOAT64_MIN DBL_MIN
+*/
+
+// portability / compiler settings
+#if defined(_WIN32) && !defined(WINDED)
+
+#if defined(_M_IX86)
+#define __i386__ 1
+#endif
+
+#elif POSIX
+#if defined( OSX ) && defined( CARBON_WORKAROUND )
+#define DWORD unsigned int
+#else
+typedef unsigned int DWORD;
+#endif
+typedef unsigned short WORD;
+typedef void * HINSTANCE;
+#define _MAX_PATH PATH_MAX
+#define __cdecl
+#define __stdcall
+#define __declspec
+
+#endif // defined(_WIN32) && !defined(WINDED)
+
+#define MAX_FILEPATH 512
+
+// Defines MAX_PATH
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+#ifdef _WIN32
+#define MAX_UNICODE_PATH 32767
+#else
+#define MAX_UNICODE_PATH MAX_PATH
+#endif
+
+#define MAX_UNICODE_PATH_IN_UTF8 MAX_UNICODE_PATH*4
+
+#if !defined( offsetof )
+ #ifdef __GNUC__
+ #define offsetof( type, var ) __builtin_offsetof( type, var )
+ #else
+ #define offsetof(s,m) (size_t)&(((s *)0)->m)
+ #endif
+#endif // !defined( offsetof )
+
+
+#define ALIGN_VALUE( val, alignment ) ( ( val + alignment - 1 ) & ~( alignment - 1 ) ) // need macro for constant expression
+
+// Used to step into the debugger
+#if defined( _WIN32 ) && !defined( _X360 )
+#define DebuggerBreak() __debugbreak()
+#elif defined( _X360 )
+#define DebuggerBreak() DebugBreak()
+#else
+ // On OSX, SIGTRAP doesn't really stop the thread cold when debugging.
+ // So if being debugged, use INT3 which is precise.
+#ifdef OSX
+#define DebuggerBreak() if ( Plat_IsInDebugSession() ) { __asm ( "int $3" ); } else { raise(SIGTRAP); }
+#else
+#define DebuggerBreak() raise(SIGTRAP)
+#endif
+#endif
+#define DebuggerBreakIfDebugging() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
+
+#ifdef STAGING_ONLY
+#define DebuggerBreakIfDebugging_StagingOnly() if ( !Plat_IsInDebugSession() ) ; else DebuggerBreak()
+#else
+#define DebuggerBreakIfDebugging_StagingOnly()
+#endif
+
+// Allows you to specify code that should only execute if we are in a staging build. Otherwise the code noops.
+#ifdef STAGING_ONLY
+#define STAGING_ONLY_EXEC( _exec ) do { _exec; } while (0)
+#else
+#define STAGING_ONLY_EXEC( _exec ) do { } while (0)
+#endif
+
+// C functions for external declarations that call the appropriate C++ methods
+#ifndef EXPORT
+ #ifdef _WIN32
+ #define EXPORT _declspec( dllexport )
+ #else
+ #define EXPORT /* */
+ #endif
+#endif
+
+#if defined __i386__ && !defined __linux__
+ #define id386 1
+#else
+ #define id386 0
+#endif // __i386__
+
+// decls for aligning data
+#ifdef _WIN32
+ #define DECL_ALIGN(x) __declspec(align(x))
+
+#elif GNUC
+ #define DECL_ALIGN(x) __attribute__((aligned(x)))
+#else
+ #define DECL_ALIGN(x) /* */
+#endif
+
+#ifdef _MSC_VER
+// MSVC has the align at the start of the struct
+#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
+#elif defined( GNUC )
+// gnuc has the align decoration at the end
+#define ALIGN4
+#define ALIGN8
+#define ALIGN16
+#define ALIGN32
+#define ALIGN128
+
+#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
+#error
+#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)(uintp)( p ) )
+
+
+//-----------------------------------------------------------------------------
+// Stack-based allocation related helpers
+//-----------------------------------------------------------------------------
+#if defined( GNUC )
+ #define stackalloc( _size ) alloca( ALIGN_VALUE( _size, 16 ) )
+#ifdef _LINUX
+ #define mallocsize( _p ) ( malloc_usable_size( _p ) )
+#elif defined(OSX)
+ #define mallocsize( _p ) ( malloc_size( _p ) )
+#else
+#error
+#endif
+#elif defined ( _WIN32 )
+ #define stackalloc( _size ) _alloca( ALIGN_VALUE( _size, 16 ) )
+ #define mallocsize( _p ) ( _msize( _p ) )
+#endif
+
+#define stackfree( _p ) 0
+
+// Linux 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.
+#ifdef POSIX
+ #define CONSTRUCT_EARLY __attribute__((init_priority(101)))
+#else
+ #define CONSTRUCT_EARLY
+ #endif
+
+#if defined(_MSC_VER)
+ #define SELECTANY __declspec(selectany)
+ #define RESTRICT __restrict
+ #define RESTRICT_FUNC __declspec(restrict)
+ #define FMTFUNCTION( a, b )
+#elif defined(GNUC)
+ #define SELECTANY __attribute__((weak))
+ #if defined(LINUX) && !defined(DEDICATED)
+ #define RESTRICT
+ #else
+ #define RESTRICT __restrict
+ #endif
+ #define RESTRICT_FUNC
+ // squirrel.h does a #define printf DevMsg which leads to warnings when we try
+ // to use printf as the prototype format function. Using __printf__ instead.
+ #define FMTFUNCTION( fmtargnumber, firstvarargnumber ) __attribute__ (( format( __printf__, fmtargnumber, firstvarargnumber )))
+#else
+ #define SELECTANY static
+ #define RESTRICT
+ #define RESTRICT_FUNC
+ #define FMTFUNCTION( a, b )
+#endif
+
+#if defined( _WIN32 )
+
+ // 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 )
+
+ #define DLL_LOCAL
+
+#elif defined GNUC
+// Used for dll exporting and importing
+#define DLL_EXPORT extern "C" __attribute__ ((visibility("default")))
+#define DLL_IMPORT extern "C"
+
+// Can't use extern "C" when DLL exporting a class
+#define DLL_CLASS_EXPORT __attribute__ ((visibility("default")))
+#define DLL_CLASS_IMPORT
+
+// Can't use extern "C" when DLL exporting a global
+#define DLL_GLOBAL_EXPORT extern __attribute ((visibility("default")))
+#define DLL_GLOBAL_IMPORT extern
+
+#define DLL_LOCAL __attribute__ ((visibility("hidden")))
+
+#else
+#error "Unsupported Platform."
+#endif
+
+// Used for standard calling conventions
+#if defined( _WIN32 ) && !defined( _X360 )
+ #define STDCALL __stdcall
+ #define FASTCALL __fastcall
+ #define FORCEINLINE __forceinline
+ // 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 __forceinline
+#elif defined( _X360 )
+ #define STDCALL __stdcall
+ #ifdef FORCEINLINE
+ #undef FORCEINLINE
+#endif
+ #define FORCEINLINE __forceinline
+ #define FORCEINLINE_TEMPLATE __forceinline
+ #else
+ #define STDCALL
+ #define FASTCALL
+ #ifdef _LINUX_DEBUGGABLE
+ #define FORCEINLINE
+ #else
+ #define FORCEINLINE inline __attribute__ ((always_inline))
+ #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 __stdcall __attribute__ ((__stdcall__))
+#endif
+
+// Force a function call site -not- to inlined. (useful for profiling)
+#define DONT_INLINE(a) (((int)(a)+1)?(a):(a))
+
+// 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.
+#ifdef _MSC_VER
+ #define HINT(THE_HINT) __assume((THE_HINT))
+#else
+ #define HINT(THE_HINT) 0
+#endif
+
+// 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();
+
+
+#ifdef _WIN32
+
+// 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
+#pragma warning(disable : 4481) // warning C4481: nonstandard extension used: override specifier 'override'
+#pragma warning(disable : 4748) // warning C4748: /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function
+
+#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
+
+
+#endif // _WIN32
+
+#if defined( LINUX ) && ((__GNUC__ * 100) + __GNUC_MINOR__) >= 406
+ // based on some Jonathan Wakely macros on the net...
+ #define GCC_DIAG_STR(s) #s
+ #define GCC_DIAG_JOINSTR(x,y) GCC_DIAG_STR(x ## y)
+ #define GCC_DIAG_DO_PRAGMA(x) _Pragma (#x)
+ #define GCC_DIAG_PRAGMA(x) GCC_DIAG_DO_PRAGMA(GCC diagnostic x)
+
+ #define GCC_DIAG_PUSH_OFF(x) GCC_DIAG_PRAGMA(push) GCC_DIAG_PRAGMA(ignored GCC_DIAG_JOINSTR(-W,x))
+ #define GCC_DIAG_POP() GCC_DIAG_PRAGMA(pop)
+#else
+ #define GCC_DIAG_PUSH_OFF(x)
+ #define GCC_DIAG_POP()
+#endif
+
+#ifdef LINUX
+#pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
+#pragma GCC diagnostic ignored "-Wpointer-arith" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
+#pragma GCC diagnostic ignored "-Wswitch" // enumeration values not handled in switch
+#endif
+
+#ifdef OSX
+#pragma GCC diagnostic ignored "-Wconversion-null" // passing NULL to non-pointer argument 1
+#pragma GCC diagnostic ignored "-Wnull-arithmetic" // NULL used in arithmetic. Ie, vpanel == NULL where VPANEL is uint.
+#pragma GCC diagnostic ignored "-Wswitch-enum" // enumeration values not handled in switch
+#pragma GCC diagnostic ignored "-Wswitch" // enumeration values not handled in switch
+#endif
+
+
+// When we port to 64 bit, we'll have to resolve the int, ptr vs size_t 32/64 bit problems...
+#if !defined( _WIN64 )
+#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
+
+
+#ifdef POSIX
+#define _stricmp stricmp
+#define strcmpi stricmp
+#define stricmp strcasecmp
+#define _vsnprintf vsnprintf
+#define _alloca alloca
+#ifdef _snprintf
+#undef _snprintf
+#endif
+#define _snprintf snprintf
+#define GetProcAddress dlsym
+#define _chdir chdir
+#define _strnicmp strnicmp
+#define strnicmp strncasecmp
+#define _getcwd getcwd
+#define _snwprintf swprintf
+#define swprintf_s swprintf
+#define wcsicmp _wcsicmp
+#define _wcsicmp wcscmp
+#define _finite finite
+#define _tempnam tempnam
+#define _unlink unlink
+#define _access access
+#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)
+
+typedef uint32 HMODULE;
+typedef void *HANDLE;
+#endif
+
+//-----------------------------------------------------------------------------
+// fsel
+//-----------------------------------------------------------------------------
+#ifndef _X360
+
+static FORCEINLINE float fsel(float fComparand, float fValGE, float fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+static FORCEINLINE double fsel(double fComparand, double fValGE, double fLT)
+{
+ return fComparand >= 0 ? fValGE : fLT;
+}
+
+#else
+
+// __fsel(double fComparand, double fValGE, double fLT) == fComparand >= 0 ? fValGE : fLT
+// this is much faster than if ( aFloat > 0 ) { x = .. }
+#define fsel __fsel
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// FP exception handling
+//-----------------------------------------------------------------------------
+//#define CHECK_FLOAT_EXCEPTIONS 1
+
+#if !defined( _X360 )
+#if defined( _MSC_VER )
+
+ #if defined( PLATFORM_WINDOWS_PC64 )
+ inline void SetupFPUControlWord()
+ {
+ }
+ #else
+ 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
+ #endif
+
+#else
+
+ inline void SetupFPUControlWord()
+ {
+ __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 // _MSC_VER
+
+#else
+
+ #ifdef _DEBUG
+ FORCEINLINE bool IsFPUControlWordSet()
+ {
+ float f = 0.996f;
+ union
+ {
+ double flResult;
+ int pResult[2];
+ };
+ flResult = __fctiw( f );
+ return ( pResult[1] == 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 // _X360
+
+//-----------------------------------------------------------------------------
+// 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);
+}
+
+template <typename T>
+inline T QWordSwapC( T dw )
+{
+ // Assert sizes passed to this are already correct, otherwise
+ // the cast to uint64 * below is unsafe and may have wrong results
+ // or even crash.
+ PLAT_COMPILE_TIME_ASSERT( sizeof( dw ) == sizeof(uint64) );
+
+ uint64 temp;
+
+ temp = *((uint64 *)&dw) >> 56;
+ temp |= ((*((uint64 *)&dw) & 0x00FF000000000000ull) >> 40);
+ temp |= ((*((uint64 *)&dw) & 0x0000FF0000000000ull) >> 24);
+ temp |= ((*((uint64 *)&dw) & 0x000000FF00000000ull) >> 8);
+ temp |= ((*((uint64 *)&dw) & 0x00000000FF000000ull) << 8);
+ temp |= ((*((uint64 *)&dw) & 0x0000000000FF0000ull) << 24);
+ temp |= ((*((uint64 *)&dw) & 0x000000000000FF00ull) << 40);
+ temp |= ((*((uint64 *)&dw) & 0x00000000000000FFull) << 56);
+
+ return *((T*)&temp);
+}
+
+//-------------------------------------
+// Fast swaps
+//-------------------------------------
+
+#if defined( _X360 )
+
+ #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( _MSC_VER ) && !defined( PLATFORM_WINDOWS_PC64 )
+
+ #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
+
+// No ASM implementation for this yet
+#define QWordSwap QWordSwapC
+
+//-------------------------------------
+// The typically used methods.
+//-------------------------------------
+
+#if defined(__i386__) && !defined(VALVE_LITTLE_ENDIAN)
+#define VALVE_LITTLE_ENDIAN 1
+#endif
+
+#if defined( _SGI_SOURCE ) || defined( _X360 )
+#define VALVE_BIG_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(VALVE_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 LittleQWord( 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(VALVE_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 LittleQWord( val ) QWordSwap( 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 uint64 LittleQWord( uint64 val ) { int test = 1; return ( *(char *)&test == 1 ) ? val : QWordSwap( 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 _X360
+FORCEINLINE unsigned long LoadLittleDWord( const unsigned long *base, unsigned int dwordIndex )
+ {
+ return __loadwordbytereverse( dwordIndex<<2, base );
+ }
+
+FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword )
+ {
+ __storewordbytereverse( dword, dwordIndex<<2, base );
+ }
+#else
+FORCEINLINE unsigned long LoadLittleDWord( const unsigned long *base, unsigned int dwordIndex )
+ {
+ return LittleDWord( base[dwordIndex] );
+ }
+
+FORCEINLINE void StoreLittleDWord( unsigned long *base, unsigned int dwordIndex, unsigned long dword )
+ {
+ base[dwordIndex] = LittleDWord(dword);
+ }
+#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
+
+
+// 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_USTime(); // Time in microseconds.
+PLATFORM_INTERFACE char * Plat_ctime( const time_t *timep, char *buf, size_t bufsize );
+PLATFORM_INTERFACE void Plat_GetModuleFilename( char *pOut, int nMaxBytes );
+
+PLATFORM_INTERFACE void Plat_ExitProcess( int nCode );
+
+//called to exit the process due to a fatal error. This allows for the application to handle providing a hook as well which can be called
+//before exiting
+PLATFORM_INTERFACE void Plat_ExitProcessWithError( int nCode, bool bGenerateMinidump = false );
+
+//sets the callback that will be triggered by Plat_ExitProcessWithError. NULL is valid. The return value true indicates that
+//the exit has been handled and no further processing should be performed. False will cause a minidump to be generated, and the process
+//to be terminated
+typedef bool (*ExitProcessWithErrorCBFn)( int nCode );
+PLATFORM_INTERFACE void Plat_SetExitProcessWithErrorCB( ExitProcessWithErrorCBFn pfnCB );
+
+PLATFORM_INTERFACE struct tm * Plat_gmtime( const time_t *timep, struct tm *result );
+PLATFORM_INTERFACE time_t Plat_timegm( struct tm *timeptr );
+PLATFORM_INTERFACE struct tm * Plat_localtime( const time_t *timep, struct tm *result );
+
+#if defined( _WIN32 ) && defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
+ extern "C" unsigned __int64 __rdtsc();
+ #pragma intrinsic(__rdtsc)
+#endif
+
+inline uint64 Plat_Rdtsc()
+{
+#if defined( _X360 )
+ return ( uint64 )__mftb32();
+#elif defined( _WIN64 )
+ return ( uint64 )__rdtsc();
+#elif defined( _WIN32 )
+ #if defined( _MSC_VER ) && ( _MSC_VER >= 1400 )
+ return ( uint64 )__rdtsc();
+ #else
+ __asm rdtsc;
+ __asm ret;
+ #endif
+#elif defined( __i386__ )
+ uint64 val;
+ __asm__ __volatile__ ( "rdtsc" : "=A" (val) );
+ return val;
+#elif defined( __x86_64__ )
+ uint32 lo, hi;
+ __asm__ __volatile__ ( "rdtsc" : "=a" (lo), "=d" (hi));
+ return ( ( ( uint64 )hi ) << 32 ) | lo;
+#else
+ #error
+#endif
+}
+
+// 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.
+
+ uint32 m_nModel;
+ uint32 m_nFeatures[3];
+
+ CPUInformation(): m_Size(0){}
+};
+
+// Have to return a pointer, not a reference, because references are not compatible with the
+// extern "C" implied by PLATFORM_INTERFACE.
+PLATFORM_INTERFACE const CPUInformation* GetCPUInformation();
+
+#define MEMORY_INFORMATION_VERSION 0
+
+struct MemoryInformation
+{
+ int m_nStructVersion;
+
+ uint m_nPhysicalRamMbTotal;
+ uint m_nPhysicalRamMbAvailable;
+
+ uint m_nVirtualRamMbTotal;
+ uint m_nVirtualRamMbAvailable;
+
+ inline MemoryInformation()
+ {
+ memset( this, 0, sizeof( *this ) );
+ m_nStructVersion = MEMORY_INFORMATION_VERSION;
+ }
+};
+
+// Returns true if the passed in MemoryInformation structure was filled out, otherwise false.
+PLATFORM_INTERFACE bool GetMemoryInformation( MemoryInformation *pOutMemoryInfo );
+
+PLATFORM_INTERFACE float GetCPUUsage();
+
+PLATFORM_INTERFACE void GetCurrentDate( int *pDay, int *pMonth, int *pYear );
+
+// ---------------------------------------------------------------------------------- //
+// Performance Monitoring Events - L2 stats etc...
+// ---------------------------------------------------------------------------------- //
+PLATFORM_INTERFACE void InitPME();
+PLATFORM_INTERFACE void ShutdownPME();
+
+//-----------------------------------------------------------------------------
+// Thread related functions
+//-----------------------------------------------------------------------------
+
+// Sets a hardware data breakpoint on the given address. Currently Win32-only.
+// Specify 1, 2, or 4 bytes for nWatchBytes; pass 0 to unregister the address.
+PLATFORM_INTERFACE void Plat_SetHardwareDataBreakpoint( const void *pAddress, int nWatchBytes, bool bBreakOnRead );
+
+// Apply current hardware data breakpoints to a newly created thread.
+PLATFORM_INTERFACE void Plat_ApplyHardwareDataBreakpointsToNewThread( unsigned long dwThreadID );
+
+//-----------------------------------------------------------------------------
+// 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();
+
+//-----------------------------------------------------------------------------
+// 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 _X360
+#define Plat_FastMemset XMemSet
+#define Plat_FastMemcpy XMemCpy
+#else
+#define Plat_FastMemset memset
+#define Plat_FastMemcpy memcpy
+#endif
+
+//-----------------------------------------------------------------------------
+// Returns true if debugger attached, false otherwise
+//-----------------------------------------------------------------------------
+#if defined(_WIN32) || defined(LINUX) || defined(OSX)
+PLATFORM_INTERFACE bool Plat_IsInDebugSession();
+PLATFORM_INTERFACE void Plat_DebugString( const char * );
+#else
+inline bool Plat_IsInDebugSession( bool bForceRecheck = false ) { return false; }
+#define Plat_DebugString(s) ((void)0)
+#endif
+
+//-----------------------------------------------------------------------------
+// Returns true if running on a 64 bit (windows) OS
+//-----------------------------------------------------------------------------
+PLATFORM_INTERFACE bool Is64BitOS();
+
+
+//-----------------------------------------------------------------------------
+// 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)
+
+inline const char *GetPlatformExt( void )
+{
+ return IsX360() ? ".360" : "";
+}
+
+// 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.
+//-----------------------------------------------------------------------------
+#include "tier0/fasttimer.h"
+
+#if defined( _X360 )
+#include "xbox/xbox_core.h"
+#endif
+
+//-----------------------------------------------------------------------------
+// Methods to invoke the constructor, copy constructor, and destructor
+//-----------------------------------------------------------------------------
+
+template <class T>
+inline T* Construct( T* pMemory )
+{
+ return reinterpret_cast<T*>(::new( pMemory ) T);
+}
+
+template <class T, typename ARG1>
+inline T* Construct( T* pMemory, ARG1 a1 )
+{
+ return reinterpret_cast<T*>(::new( pMemory ) T( a1 ));
+}
+
+template <class T, typename ARG1, typename ARG2>
+inline T* Construct( T* pMemory, ARG1 a1, ARG2 a2 )
+{
+ return reinterpret_cast<T*>(::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 reinterpret_cast<T*>(::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 reinterpret_cast<T*>(::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 reinterpret_cast<T*>(::new( pMemory ) T( a1, a2, a3, a4, a5 ));
+}
+
+template <class T, class P>
+inline void ConstructOneArg( T* pMemory, P const& arg)
+{
+ ::new( pMemory ) T(arg);
+}
+
+template <class T, class P1, class P2 >
+inline void ConstructTwoArg( T* pMemory, P1 const& arg1, P2 const& arg2)
+{
+ ::new( pMemory ) T(arg1, arg2);
+}
+
+template <class T, class P1, class P2, class P3 >
+inline void ConstructThreeArg( T* pMemory, P1 const& arg1, P2 const& arg2, P3 const& arg3)
+{
+ ::new( pMemory ) T(arg1, arg2, arg3);
+}
+
+template <class T>
+inline T* CopyConstruct( T* pMemory, T const& src )
+{
+ return reinterpret_cast<T*>(::new( pMemory ) T(src));
+}
+
+template <class T>
+inline void Destruct( T* pMemory )
+{
+ pMemory->~T();
+
+#ifdef _DEBUG
+ memset( reinterpret_cast<void*>( pMemory ), 0xDD, sizeof(T) );
+#endif
+}
+
+// The above will error when binding to a type of: foo(*)[] -- there is no provision in c++ for knowing how many objects
+// to destruct without preserving the count and calling the necessary destructors.
+template <class T, size_t N>
+inline void Destruct( T (*pMemory)[N] )
+{
+ for ( size_t i = 0; i < N; i++ )
+ {
+ (pMemory[i])->~T();
+ }
+
+#ifdef _DEBUG
+ memset( reinterpret_cast<void*>( pMemory ), 0xDD, sizeof(*pMemory) );
+#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 0 // defined( PLATFORM_WINDOWS_PC )
+
+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
+
+
+// Watchdog timer support. Call Plat_BeginWatchdogTimer( nn ) to kick the timer off. if you don't call
+// Plat_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
+// Plat_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.
+PLATFORM_INTERFACE void Plat_BeginWatchdogTimer( int nSecs );
+PLATFORM_INTERFACE void Plat_EndWatchdogTimer( void );
+PLATFORM_INTERFACE int Plat_GetWatchdogTime( void );
+
+typedef void (*Plat_WatchDogHandlerFunction_t)(void);
+PLATFORM_INTERFACE void Plat_SetWatchdogHandlerFunction( Plat_WatchDogHandlerFunction_t function );
+
+
+//-----------------------------------------------------------------------------
+
+#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 )
+#endif
+
+
+#endif /* PLATFORM_H */
diff --git a/public/tier0/pmc360.h b/public/tier0/pmc360.h
new file mode 100644
index 0000000..ebae346
--- /dev/null
+++ b/public/tier0/pmc360.h
@@ -0,0 +1,73 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Analogous to l2cache.h, this class represents information gleaned
+// from the 360's Performance Monitor Counters. In particular we
+// are interested in l2 cache misses and load-hit-stores.
+//
+//=============================================================================//
+#ifndef CPMCDATA_H
+#define CPMCDATA_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#ifndef _X360
+#error This file must only be compiled for XBOX360!
+#endif
+
+
+// Warning:
+// As written, this class only supports profiling thread 0, processor 0.
+
+class CPMCData
+{
+public:
+
+ CPMCData();
+ ~CPMCData() {};
+
+ void Start( void );
+ void End( void );
+
+ /// This function should be called exactly once during the lifespan of the program;
+ /// it will set up the counters to record the information we are interested in.
+ /// This will stomp on whoever else might have set the performance counters elsewhere
+ /// in the game.
+ static void InitializeOnceProgramWide( void );
+ static bool IsInitialized();
+
+ //-------------------------------------------------------------------------
+ // GetL2CacheMisses
+ //-------------------------------------------------------------------------
+ uint64 GetL2CacheMisses( void ) const
+ {
+ return m_Delta.L2CacheMiss;
+ }
+
+ uint64 GetLHS( void ) const
+ {
+ return m_Delta.LHS;
+ }
+
+/*
+#ifdef DBGFLAG_VALIDATE
+ void Validate( CValidator &validator, tchar *pchName ); // Validate our internal structures
+#endif // DBGFLAG_VALIDATE
+*/
+
+private:
+ /// represents saved numbers from the counters we are interested in
+ struct PMCounters
+ {
+ uint64 L2CacheMiss;
+ uint64 LHS; ///< load hit store
+
+ PMCounters(int64 _l2cm, int64 _lhs ) : L2CacheMiss(_l2cm), LHS(_lhs) {};
+ PMCounters() : L2CacheMiss(0), LHS(0) {};
+ };
+
+ PMCounters m_OnStart; ///< values when we began the timer
+ PMCounters m_Delta ; ///< computed total delta between start/stop
+};
+
+#endif // CPMCDATA_H \ No newline at end of file
diff --git a/public/tier0/pointeroverride.asm b/public/tier0/pointeroverride.asm
new file mode 100644
index 0000000..e75ed65
--- /dev/null
+++ b/public/tier0/pointeroverride.asm
@@ -0,0 +1,17 @@
+.model flat, C
+
+.data
+ __imp__EncodePointer@4 dd dummy
+ __imp__DecodePointer@4 dd dummy
+
+ EXTERNDEF __imp__EncodePointer@4 : DWORD
+ EXTERNDEF __imp__DecodePointer@4 : DWORD
+
+.code
+ dummy proc
+ mov eax, [esp+4]
+ ret 4
+ dummy endp
+
+end
+ \ No newline at end of file
diff --git a/public/tier0/progressbar.h b/public/tier0/progressbar.h
new file mode 100644
index 0000000..ce28afe
--- /dev/null
+++ b/public/tier0/progressbar.h
@@ -0,0 +1,23 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Provide a shared place for library fucntions to report progress % for display
+//
+//=============================================================================//
+
+#ifndef PROGRESSBAR_H
+#define PROGRESSBAR_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+PLATFORM_INTERFACE void ReportProgress(char const *job_name, int total_units_to_do,
+ int n_units_completed);
+
+typedef void (*ProgressReportHandler_t)( char const*, int, int );
+
+// install your own handler. returns previous handler
+PLATFORM_INTERFACE ProgressReportHandler_t InstallProgressReportHandler( ProgressReportHandler_t pfn);
+
+
+#endif
diff --git a/public/tier0/protected_things.h b/public/tier0/protected_things.h
new file mode 100644
index 0000000..8cbfa92
--- /dev/null
+++ b/public/tier0/protected_things.h
@@ -0,0 +1,271 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef PROTECTED_THINGS_H
+#define PROTECTED_THINGS_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+// This header tries to prevent people from using potentially dangerous functions
+// (like the notorious non-null-terminating strncpy) and functions that will break
+// VCR mode (like time, input, registry, etc).
+//
+// This header should be included by ALL of our source code.
+
+// Eventually, ALL of these should be protected, but one man can only accomplish so much in
+// one day AND work on features too!
+#if defined( PROTECTED_STRINGS_ENABLE ) && !defined(DISABLE_PROTECTED_STRINGS)
+
+ #if defined( printf )
+ #undef printf
+ #endif
+ #define printf printf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wprintf )
+ #undef wprintf
+ #endif
+ #define wprintf wprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( strcmp )
+ #undef strcmp
+ #endif
+ #define strcmp strcmp__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wcscmp )
+ #undef wcscmp
+ #endif
+ #define wcscmp wcscmp__HEY_YOU__USE_VSTDLIB
+
+ #if defined( strncpy )
+ #undef strncpy
+ #endif
+ #define strncpy strncpy__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wcsncpy )
+ #undef wcsncpy
+ #endif
+ #define wcsncpy wcsncpy__HEY_YOU__USE_VSTDLIB
+
+ #if defined( strlen )
+ #undef strlen
+ #endif
+ #define strlen strlen__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wcslen )
+ #undef wcslen
+ #endif
+ #define wcslen wcslen__HEY_YOU__USE_VSTDLIB
+
+ #if defined( Q_strlen )
+ #undef Q_strlen
+ #endif
+ #define Q_strlen Q_strlen__HEY_YOU__USE_VSTDLIB
+
+ #if defined( _snprintf )
+ #undef _snprintf
+ #endif
+ #define _snprintf snprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( _snwprintf )
+ #undef _snwprintf
+ #endif
+ #define _snwprintf snwprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( sprintf )
+ #undef sprintf
+ #endif
+ #define sprintf sprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( swprintf )
+ #undef swprintf
+ #endif
+ #define swprintf swprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( vsprintf )
+ #undef vsprintf
+ #endif
+ #define vsprintf vsprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( vswprintf )
+ #undef vswprintf
+ #endif
+ #define vswprintf vswprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( _vsnprintf )
+ #undef _vsnprintf
+ #endif
+ #define _vsnprintf vsnprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( _vsnwprintf )
+ #undef _vsnwprintf
+ #endif
+ #define _vsnwprintf vsnwprintf__HEY_YOU__USE_VSTDLIB
+
+ #if defined( strcat )
+ #undef strcat
+ #endif
+ #define strcat strcat__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wcscat )
+ #undef wcscat
+ #endif
+ #define wcscat wcscat__HEY_YOU__USE_VSTDLIB
+
+ #if defined( strncat )
+ #undef strncat
+ #endif
+ #define strncat strncat__HEY_YOU__USE_VSTDLIB
+
+ #if defined( wcsncat )
+ #undef wcsncat
+ #endif
+ #define wcsncat wcsncat__HEY_YOU__USE_VSTDLIB
+
+#endif
+
+
+#if defined( PROTECTED_THINGS_ENABLE ) && !defined( _X360 ) && !defined(DISABLE_PROTECTED_THINGS)
+
+ #if defined( GetTickCount )
+ #undef GetTickCount
+ #endif
+ #define GetTickCount GetTickCount__USE_VCR_MODE
+
+
+ #if defined( timeGetTime )
+ #undef timeGetTime
+ #endif
+ #define timeGetTime timeGetTime__USE_VCR_MODE
+ #if defined( clock )
+ #undef clock
+ #endif
+ #define time time__USE_VCR_MODE
+
+
+ #if defined( recvfrom )
+ #undef recvfrom
+ #endif
+ #define recvfrom recvfrom__USE_VCR_MODE
+
+
+ #if defined( GetCursorPos )
+ #undef GetCursorPos
+ #endif
+ #define GetCursorPos GetCursorPos__USE_VCR_MODE
+
+
+ #if defined( ScreenToClient )
+ #undef ScreenToClient
+ #endif
+ #define ScreenToClient ScreenToClient__USE_VCR_MODE
+
+
+ #if defined( GetCommandLine )
+ #undef GetCommandLine
+ #endif
+ #define GetCommandLine GetCommandLine__USE_VCR_MODE
+
+
+ #if defined( RegOpenKeyEx )
+ #undef RegOpenKeyEx
+ #endif
+ #define RegOpenKeyEx RegOpenKeyEx__USE_VCR_MODE
+
+
+ #if defined( RegOpenKey )
+ #undef RegOpenKey
+ #endif
+ #define RegOpenKey RegOpenKey__USE_VCR_MODE
+
+
+ #if defined( RegSetValueEx )
+ #undef RegSetValueEx
+ #endif
+ #define RegSetValueEx RegSetValueEx__USE_VCR_MODE
+
+
+ #if defined( RegSetValue )
+ #undef RegSetValue
+ #endif
+ #define RegSetValue RegSetValue__USE_VCR_MODE
+
+
+ #if defined( RegQueryValueEx )
+ #undef RegQueryValueEx
+ #endif
+ #define RegQueryValueEx RegQueryValueEx__USE_VCR_MODE
+
+
+ #if defined( RegQueryValue )
+ #undef RegQueryValue
+ #endif
+ #define RegQueryValue RegQueryValue__USE_VCR_MODE
+
+
+ #if defined( RegCreateKeyEx )
+ #undef RegCreateKeyEx
+ #endif
+ #define RegCreateKeyEx RegCreateKeyEx__USE_VCR_MODE
+
+
+ #if defined( RegCreateKey )
+ #undef RegCreateKey
+ #endif
+ #define RegCreateKey RegCreateKey__USE_VCR_MODE
+
+
+ #if defined( RegCloseKey )
+ #undef RegCloseKey
+ #endif
+ #define RegCloseKey RegCloseKey__USE_VCR_MODE
+
+
+ #if defined( GetNumberOfConsoleInputEvents )
+ #undef GetNumberOfConsoleInputEvents
+ #endif
+ #define GetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents__USE_VCR_MODE
+
+
+ #if defined( ReadConsoleInput )
+ #undef ReadConsoleInput
+ #endif
+ #define ReadConsoleInput ReadConsoleInput__USE_VCR_MODE
+
+
+ #if defined( GetAsyncKeyState )
+ #undef GetAsyncKeyState
+ #endif
+ #define GetAsyncKeyState GetAsyncKeyState__USE_VCR_MODE
+
+
+ #if defined( GetKeyState )
+ #undef GetKeyState
+ #endif
+ #define GetKeyState GetKeyState__USE_VCR_MODE
+
+
+ #if defined( CreateThread )
+ #undef CreateThread
+ #endif
+ #define CreateThread CreateThread__USE_VCR_MODE
+
+ #if defined( WaitForSingleObject )
+ #undef WaitForSingleObject
+ #endif
+ #define WaitForSingleObject WaitForSingleObject__USE_VCR_MODE
+
+ #if defined( EnterCriticalSection )
+ #undef EnterCriticalSection
+ #endif
+ #define EnterCriticalSection EnterCriticalSection__USE_VCR_MODE
+
+#endif
+
+
+#endif // PROTECTED_THINGS_H
diff --git a/public/tier0/stacktools.h b/public/tier0/stacktools.h
new file mode 100644
index 0000000..c356b8c
--- /dev/null
+++ b/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/public/tier0/systeminformation.h b/public/tier0/systeminformation.h
new file mode 100644
index 0000000..f9ba59e
--- /dev/null
+++ b/public/tier0/systeminformation.h
@@ -0,0 +1,56 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//
+//=============================================================================//
+
+#ifndef SYSTEMINFORMATION_H
+#define SYSTEMINFORMATION_H
+
+#ifdef _WIN32
+ #pragma once
+#endif
+
+#ifndef PLATFORM_INTERFACE
+ #define PLATFORM_INTERFACE
+#endif
+
+//
+// Defines a possible outcome of a system call
+//
+enum SYSTEM_CALL_RESULT_t
+{
+ SYSCALL_SUCCESS = 0, // System call succeeded
+ SYSCALL_FAILED = 1, // System call failed
+ SYSCALL_NOPROC = 2, // Failed to find required system procedure
+ SYSCALL_NODLL = 3, // Failed to find or load required system module
+ SYSCALL_UNSUPPORTED = 4, // System call unsupported on the OS
+};
+
+
+//
+// Information about paged pool memory
+//
+struct PAGED_POOL_INFO_t
+{
+ unsigned long numPagesUsed; // Number of Paged Pool pages used
+ unsigned long numPagesFree; // Number of Paged Pool pages free
+};
+
+//
+// Plat_GetMemPageSize
+// Returns the size of a memory page in kilobytes.
+//
+PLATFORM_INTERFACE unsigned long Plat_GetMemPageSize();
+
+//
+// Plat_GetPagedPoolInfo
+// Fills in the paged pool info structure if successful.
+//
+PLATFORM_INTERFACE SYSTEM_CALL_RESULT_t Plat_GetPagedPoolInfo( PAGED_POOL_INFO_t *pPPI );
+
+
+
+#endif // #ifndef SYSTEMINFORMATION_H
diff --git a/public/tier0/testthread.h b/public/tier0/testthread.h
new file mode 100644
index 0000000..6ffda65
--- /dev/null
+++ b/public/tier0/testthread.h
@@ -0,0 +1,60 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: exposes testing thread functions
+//
+//=============================================================================
+
+#ifndef TESTTHREAD_H
+#define TESTTHREAD_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/dbg.h"
+
+// test callback
+typedef void (STDCALL *TestFunc)(void *pv);
+
+// runs the test function
+DBG_INTERFACE void Test_RunTest(TestFunc func, void *pvArg);
+
+// call to give the test thread a chance to run
+// calling thread will block until the test thread yields
+// doesn't do anything if no tests are running
+DBG_INTERFACE void Test_RunFrame();
+
+// true if any tests are running, or have ran
+DBG_INTERFACE bool Test_IsActive();
+
+// sets that the test has failed
+DBG_INTERFACE void Test_SetFailed();
+
+// true if any tests have failed, due to an assert, warning, or explicit fail
+DBG_INTERFACE bool Test_HasFailed();
+
+// true if any tests have completed
+DBG_INTERFACE bool Test_HasFinished();
+
+// terminates the test thread
+DBG_INTERFACE void Test_TerminateThread();
+
+// the following functions should only be called from the test thread
+
+// yields to the main thread for a single frame
+// passing in is a count of the number of frames that have been yielded by this yield macro
+// can be used to assert if a test thread is blocked foor
+DBG_INTERFACE void TestThread_Yield();
+
+// utility functions to pause the test frame until the selected condition is true
+#define YIELD_UNTIL(x) { int iYieldCount = 0; while (!(x)) { TestThread_Yield(); iYieldCount++; if ( iYieldCount >= 100 ) { AssertMsg( false, #x ); break; } } }
+
+// use this like a while(1) loop, with break; to stop yielding
+#define YIELD_UNTIL_BREAK() for (; true; TestThread_Yield())
+
+// yields for a single frame
+#define YIELD_FRAME() { TestThread_Yield(); }
+#define YIELD_TWO_FRAMES() { TestThread_Yield(); TestThread_Yield(); }
+
+
+
+#endif // TESTTHREAD_H
diff --git a/public/tier0/threadtools.h b/public/tier0/threadtools.h
new file mode 100644
index 0000000..b0b9b1d
--- /dev/null
+++ b/public/tier0/threadtools.h
@@ -0,0 +1,1825 @@
+//========= Copyright 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 "tier0/type_traits.h"
+
+#include <limits.h>
+
+#include "tier0/platform.h"
+#include "tier0/dbg.h"
+#include "tier0/vcrmode.h"
+#include "tier0/vprof_telemetry.h"
+
+#ifdef PLATFORM_WINDOWS_PC
+#include <intrin.h>
+#endif
+
+#ifdef POSIX
+#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( _WIN32 )
+#pragma once
+#pragma warning(push)
+#pragma warning(disable:4251)
+#endif
+
+// #define THREAD_PROFILER 1
+
+#ifndef _RETAIL
+#define THREAD_MUTEX_TRACING_SUPPORTED
+#if defined(_WIN32) && defined(_DEBUG)
+#define THREAD_MUTEX_TRACING_ENABLED
+#endif
+#endif
+
+#ifdef _WIN32
+typedef void *HANDLE;
+#endif
+
+// Start thread running - error if already running
+enum ThreadPriorityEnum_t
+{
+#if defined( PLATFORM_PS3 )
+ TP_PRIORITY_NORMAL = 1001,
+ TP_PRIORITY_HIGH = 100,
+ TP_PRIORITY_LOW = 2001,
+ TP_PRIORITY_DEFAULT = 1001
+#error "Need PRIORITY_LOWEST/HIGHEST"
+#elif defined( PLATFORM_LINUX )
+ // We can use nice on Linux threads to change scheduling.
+ // pthreads on Linux only allows priority setting on
+ // real-time threads.
+ // NOTE: Lower numbers are higher priority, thus the need
+ // for TP_IS_PRIORITY_HIGHER.
+ TP_PRIORITY_DEFAULT = 0,
+ TP_PRIORITY_NORMAL = 0,
+ TP_PRIORITY_HIGH = -10,
+ TP_PRIORITY_LOW = 10,
+ TP_PRIORITY_HIGHEST = -20,
+ TP_PRIORITY_LOWEST = 19,
+#else // PLATFORM_PS3
+ TP_PRIORITY_DEFAULT = 0, // THREAD_PRIORITY_NORMAL
+ TP_PRIORITY_NORMAL = 0, // THREAD_PRIORITY_NORMAL
+ TP_PRIORITY_HIGH = 1, // THREAD_PRIORITY_ABOVE_NORMAL
+ TP_PRIORITY_LOW = -1, // THREAD_PRIORITY_BELOW_NORMAL
+ TP_PRIORITY_HIGHEST = 2, // THREAD_PRIORITY_HIGHEST
+ TP_PRIORITY_LOWEST = -2, // THREAD_PRIORITY_LOWEST
+#endif // PLATFORM_PS3
+};
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+
+const unsigned TT_INFINITE = 0xffffffff;
+
+#ifndef NO_THREAD_LOCAL
+
+#ifndef THREAD_LOCAL
+#ifdef _WIN32
+#define THREAD_LOCAL __declspec(thread)
+#elif POSIX
+#define THREAD_LOCAL __thread
+#endif
+#endif
+
+#endif // NO_THREAD_LOCAL
+
+typedef unsigned long ThreadId_t;
+
+//-----------------------------------------------------------------------------
+//
+// Simple thread creation. Differs from VCR mode/CreateThread/_beginthreadex
+// in that it accepts a standard C function rather than compiler specific one.
+//
+//-----------------------------------------------------------------------------
+FORWARD_DECLARE_HANDLE( ThreadHandle_t );
+typedef unsigned (*ThreadFunc_t)( void *pParam );
+
+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 );
+PLATFORM_INTERFACE bool ReleaseThreadHandle( ThreadHandle_t );
+
+
+//-----------------------------------------------------------------------------
+
+PLATFORM_INTERFACE void ThreadSleep(unsigned duration = 0);
+PLATFORM_INTERFACE uint 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 ); }
+PLATFORM_INTERFACE bool ThreadInMainThread();
+PLATFORM_INTERFACE void DeclareCurrentThreadIsMainThread();
+
+// 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( _WIN32 ) && !defined( _WIN64 ) && !defined( _X360 )
+extern "C" unsigned long __declspec(dllimport) __stdcall GetCurrentThreadId();
+#define ThreadGetCurrentId GetCurrentThreadId
+#endif
+
+inline void ThreadPause()
+{
+#if defined( PLATFORM_WINDOWS_PC )
+ // Intrinsic for __asm pause; from <intrin.h>
+ _mm_pause();
+#elif POSIX
+ __asm __volatile( "pause" );
+#elif defined( _X360 )
+#else
+#error "implement me"
+#endif
+}
+
+PLATFORM_INTERFACE bool ThreadJoin( ThreadHandle_t, unsigned timeout = TT_INFINITE );
+// If you're not calling ThreadJoin, you need to call ThreadDetach so pthreads on Linux knows it can
+// free the memory for this thread. Otherwise you wind up leaking threads until you run out and
+// CreateSimpleThread() will fail.
+PLATFORM_INTERFACE void ThreadDetach( ThreadHandle_t );
+
+PLATFORM_INTERFACE void ThreadSetDebugName( ThreadId_t id, const char *pszName );
+inline void ThreadSetDebugName( const char *pszName ) { ThreadSetDebugName( (ThreadId_t)-1, pszName ); }
+
+PLATFORM_INTERFACE void ThreadSetAffinity( ThreadHandle_t hThread, int nAffinityMask );
+
+//-----------------------------------------------------------------------------
+
+enum ThreadWaitResult_t
+{
+ TW_FAILED = 0xffffffff, // WAIT_FAILED
+ TW_TIMEOUT = 0x00000102, // WAIT_TIMEOUT
+};
+
+#ifdef _WIN32
+PLATFORM_INTERFACE int ThreadWaitForObjects( int nEvents, const HANDLE *pHandles, bool bWaitAll = true, unsigned timeout = TT_INFINITE );
+inline int ThreadWaitForObject( HANDLE handle, bool bWaitAll = true, unsigned timeout = TT_INFINITE ) { return ThreadWaitForObjects( 1, &handle, bWaitAll, timeout ); }
+#endif
+
+//-----------------------------------------------------------------------------
+//
+// Interlock methods. These perform very fast atomic thread
+// safe operations. These are especially relevant in a multi-core setting.
+//
+//-----------------------------------------------------------------------------
+
+#ifdef _WIN32
+#define NOINLINE
+#elif POSIX
+#define NOINLINE __attribute__ ((noinline))
+#endif
+
+// ThreadMemoryBarrier is a fence/barrier sufficient for most uses. It prevents reads
+// from moving past reads, and writes moving past writes. It is sufficient for
+// read-acquire and write-release barriers. It is not a full barrier and it does
+// not prevent reads from moving past writes -- that would require a full __sync()
+// on PPC and is significantly more expensive.
+#if defined( _X360 ) || defined( _PS3 )
+ #define ThreadMemoryBarrier() __lwsync()
+
+#elif defined(_MSC_VER)
+ // Prevent compiler reordering across this barrier. This is
+ // sufficient for most purposes on x86/x64.
+
+ #if _MSC_VER < 1500
+ // !KLUDGE! For VC 2005
+ // http://connect.microsoft.com/VisualStudio/feedback/details/100051
+ #pragma intrinsic(_ReadWriteBarrier)
+ #endif
+ #define ThreadMemoryBarrier() _ReadWriteBarrier()
+#elif defined(GNUC)
+ // Prevent compiler reordering across this barrier. This is
+ // sufficient for most purposes on x86/x64.
+ // http://preshing.com/20120625/memory-ordering-at-compile-time
+ #define ThreadMemoryBarrier() asm volatile("" ::: "memory")
+#else
+ #error Every platform needs to define ThreadMemoryBarrier to at least prevent compiler reordering
+#endif
+
+#if defined(_WIN32) && !defined(_X360)
+ #if ( _MSC_VER >= 1310 )
+ #define USE_INTRINSIC_INTERLOCKED
+ #endif
+#endif
+
+#ifdef 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 long ThreadInterlockedIncrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedIncrement( p ); }
+inline long ThreadInterlockedDecrement( long volatile *p ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedDecrement( p ); }
+inline long ThreadInterlockedExchange( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchange( p, value ); }
+inline long ThreadInterlockedExchangeAdd( long volatile *p, long value ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedExchangeAdd( p, value ); }
+inline long ThreadInterlockedCompareExchange( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return _InterlockedCompareExchange( p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( long volatile *p, long value, long comperand ) { Assert( (size_t)p % 4 == 0 ); return ( _InterlockedCompareExchange( p, value, comperand ) == comperand ); }
+#else
+PLATFORM_INTERFACE long ThreadInterlockedIncrement( long volatile * );
+PLATFORM_INTERFACE long ThreadInterlockedDecrement( long volatile * );
+PLATFORM_INTERFACE long ThreadInterlockedExchange( long volatile *, long value );
+PLATFORM_INTERFACE long ThreadInterlockedExchangeAdd( long volatile *, long value );
+PLATFORM_INTERFACE long ThreadInterlockedCompareExchange( long volatile *, long value, long comperand );
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf( long volatile *, long value, long comperand );
+#endif
+
+inline unsigned ThreadInterlockedExchangeSubtract( long volatile *p, long value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, -value ); }
+
+#if defined( USE_INTRINSIC_INTERLOCKED ) && !defined( _WIN64 )
+#define TIPTR()
+inline void *ThreadInterlockedExchangePointer( void * volatile *p, void *value ) { return (void *)_InterlockedExchange( reinterpret_cast<long volatile *>(p), reinterpret_cast<long>(value) ); }
+inline void *ThreadInterlockedCompareExchangePointer( void * volatile *p, void *value, void *comperand ) { return (void *)_InterlockedCompareExchange( reinterpret_cast<long volatile *>(p), reinterpret_cast<long>(value), reinterpret_cast<long>(comperand) ); }
+inline bool ThreadInterlockedAssignPointerIf( void * volatile *p, void *value, void *comperand ) { return ( _InterlockedCompareExchange( reinterpret_cast<long volatile *>(p), reinterpret_cast<long>(value), reinterpret_cast<long>(comperand) ) == reinterpret_cast<long>(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 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 ) ); }
+
+#if defined( PLATFORM_64BITS )
+#if defined (_WIN32)
+typedef __m128i int128;
+inline int128 int128_zero() { return _mm_setzero_si128(); }
+#else
+typedef __int128_t int128;
+#define int128_zero() 0
+#endif
+
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf128( volatile int128 *pDest, const int128 &value, const int128 &comperand ) NOINLINE;
+
+#endif
+
+PLATFORM_INTERFACE int64 ThreadInterlockedIncrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedDecrement64( int64 volatile * ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedCompareExchange64( int64 volatile *, int64 value, int64 comperand ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedExchange64( int64 volatile *, int64 value ) NOINLINE;
+PLATFORM_INTERFACE int64 ThreadInterlockedExchangeAdd64( int64 volatile *, int64 value ) NOINLINE;
+PLATFORM_INTERFACE bool ThreadInterlockedAssignIf64(volatile int64 *pDest, int64 value, int64 comperand ) NOINLINE;
+
+inline unsigned ThreadInterlockedExchangeSubtract( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); }
+inline unsigned ThreadInterlockedIncrement( unsigned volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); }
+inline unsigned ThreadInterlockedDecrement( unsigned volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); }
+inline unsigned ThreadInterlockedExchange( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); }
+inline unsigned ThreadInterlockedExchangeAdd( unsigned volatile *p, unsigned value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); }
+inline unsigned ThreadInterlockedCompareExchange( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( unsigned volatile *p, unsigned value, unsigned comperand ) { return ThreadInterlockedAssignIf( (long volatile *)p, value, comperand ); }
+
+inline int ThreadInterlockedExchangeSubtract( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); }
+inline int ThreadInterlockedIncrement( int volatile *p ) { return ThreadInterlockedIncrement( (long volatile *)p ); }
+inline int ThreadInterlockedDecrement( int volatile *p ) { return ThreadInterlockedDecrement( (long volatile *)p ); }
+inline int ThreadInterlockedExchange( int volatile *p, int value ) { return ThreadInterlockedExchange( (long volatile *)p, value ); }
+inline int ThreadInterlockedExchangeAdd( int volatile *p, int value ) { return ThreadInterlockedExchangeAdd( (long volatile *)p, value ); }
+inline int ThreadInterlockedCompareExchange( int volatile *p, int value, int comperand ) { return ThreadInterlockedCompareExchange( (long volatile *)p, value, comperand ); }
+inline bool ThreadInterlockedAssignIf( int volatile *p, int value, int comperand ) { return ThreadInterlockedAssignIf( (long 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(_LINUX) && !defined(OSX)
+// linux totally supports compiler thread locals, even across dll's.
+#define PLAT_COMPILER_SUPPORTED_THREADLOCALS 1
+#define CTHREADLOCALINTEGER( typ ) __thread int
+#define CTHREADLOCALINT __thread int
+#define CTHREADLOCALPTR( typ ) __thread typ *
+#define CTHREADLOCAL( typ ) __thread typ
+#define GETLOCAL( x ) ( x )
+#endif // _LINUX && !OSX
+
+#if defined(WIN32) || defined(OSX)
+#ifndef __AFXTLS_H__ // not compatible with some Windows headers
+#define CTHREADLOCALINT CThreadLocalInt<int>
+#define CTHREADLOCALINTEGER( typ ) CThreadLocalInt<typ>
+#define CTHREADLOCALPTR( typ ) CThreadLocalPtr<typ>
+#define CTHREADLOCAL( typ ) CThreadLocal<typ>
+#define GETLOCAL( x ) ( x.Get() )
+#endif
+#endif // WIN32 || OSX
+
+#endif // NO_THREAD_LOCALS
+
+#ifndef __AFXTLS_H__ // not compatible with some Windows headers
+#ifndef NO_THREAD_LOCAL
+
+class PLATFORM_CLASS CThreadLocalBase
+ {
+public:
+ CThreadLocalBase();
+ ~CThreadLocalBase();
+
+ void * Get() const;
+ void Set(void *);
+
+private:
+#ifdef _WIN32
+ uint32 m_index;
+#elif POSIX
+ pthread_key_t m_index;
+#endif
+ };
+
+ //---------------------------------------------------------
+
+#ifndef __AFXTLS_H__
+
+ template <class T>
+ class CThreadLocal : public CThreadLocalBase
+ {
+ public:
+ CThreadLocal()
+ {
+ COMPILE_TIME_ASSERT( sizeof(T) == sizeof(void *) );
+ }
+
+ T Get() const
+ {
+ return reinterpret_cast<T>( CThreadLocalBase::Get() );
+ }
+
+ void Set(T val)
+ {
+ CThreadLocalBase::Set( reinterpret_cast<void *>(val) );
+ }
+ };
+
+#endif
+
+ //---------------------------------------------------------
+
+template <class T = intp>
+ class CThreadLocalInt : public CThreadLocal<T>
+ {
+ public:
+ CThreadLocalInt()
+ {
+ COMPILE_TIME_ASSERT( sizeof(T) >= sizeof(int) );
+ }
+
+ operator int() const { return (int)this->Get(); }
+ int operator=( int i ) { this->Set( (intp)i ); return i; }
+
+ int operator++() { T i = this->Get(); this->Set( ++i ); return (int)i; }
+ int operator++(int) { T i = this->Get(); this->Set( i + 1 ); return (int)i; }
+
+ int operator--() { T i = this->Get(); this->Set( --i ); return (int)i; }
+ int operator--(int) { T i = this->Get(); this->Set( i - 1 ); return (int)i; }
+ };
+
+
+ //---------------------------------------------------------
+
+ template <class T>
+ class CThreadLocalPtr : private CThreadLocalBase
+ {
+ public:
+ CThreadLocalPtr() {}
+
+ operator const void *() const { return (T *)Get(); }
+ operator void *() { return (T *)Get(); }
+
+ operator const T *() const { return (T *)Get(); }
+ operator const T *() { return (T *)Get(); }
+ operator T *() { return (T *)Get(); }
+
+ int operator=( int i ) { AssertMsg( i == 0, "Only NULL allowed on integer assign" ); Set( NULL ); return 0; }
+ 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==((void*)p); }
+ bool operator!=( const T *p ) const { return operator!=((void*)p); }
+
+ T * operator->() { return (T *)Get(); }
+ T & operator *() { return *((T *)Get()); }
+
+ const T * operator->() const { return (T *)Get(); }
+ const T & operator *() const { return *((T *)Get()); }
+
+ const T & operator[]( int i ) const { return *((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;
+ };
+
+#endif // NO_THREAD_LOCAL
+#endif // !__AFXTLS_H__
+
+//-----------------------------------------------------------------------------
+//
+// 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(long) ); }
+ CInterlockedIntT( T value ) : m_value( value ) {}
+
+ T GetRaw() 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( (long *)&m_value ); }
+ T operator++(int) { return operator++() - 1; }
+
+ T operator--() { return (T)ThreadInterlockedDecrement( (long *)&m_value ); }
+ T operator--(int) { return operator--() + 1; }
+
+ bool AssignIf( T conditionValue, T newValue ) { return ThreadInterlockedAssignIf( (long *)&m_value, (long)newValue, (long)conditionValue ); }
+
+ T operator=( T newValue ) { ThreadInterlockedExchange((long *)&m_value, newValue); return m_value; }
+
+ void operator+=( T add ) { ThreadInterlockedExchangeAdd( (long *)&m_value, (long)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 ) {}
+ 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 ); }
+
+#if defined( PLATFORM_64BITS )
+ T *operator++() { return ((T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) )) + 1; }
+ T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, sizeof(T) ); }
+
+ T *operator--() { return ((T *)ThreadInterlockedExchangeAdd64( (int64 *)&m_value, -sizeof(T) )) - 1; }
+ T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd64( (int64 *)&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 ) { ThreadInterlockedExchangeAdd64( (int64 *)&m_value, add * sizeof(T) ); }
+#else
+ T *operator++() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) )) + 1; }
+ T *operator++(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&m_value, sizeof(T) ); }
+
+ T *operator--() { return ((T *)ThreadInterlockedExchangeAdd( (long *)&m_value, -sizeof(T) )) - 1; }
+ T *operator--(int) { return (T *)ThreadInterlockedExchangeAdd( (long *)&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( (long *)&m_value, add * sizeof(T) ); }
+#endif
+
+ void operator-=( int subtract ) { operator+=( -subtract ); }
+
+ 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 verification that multiple threads aren't getting into the same code at the same time.
+// Note: This is intended for use to identify problems, it doesn't provide any sort of thread safety.
+//
+//-----------------------------------------------------------------------------
+class ReentrancyVerifier
+{
+public:
+ inline ReentrancyVerifier(CInterlockedInt* counter, int sleepTimeMS)
+ : mCounter(counter)
+ {
+ Assert(mCounter != NULL);
+
+ if (++(*mCounter) != 1) {
+ DebuggerBreakIfDebugging_StagingOnly();
+ }
+
+ if (sleepTimeMS > 0)
+ {
+ ThreadSleep(sleepTimeMS);
+ }
+ }
+
+ inline ~ReentrancyVerifier()
+ {
+ if (--(*mCounter) != 0) {
+ DebuggerBreakIfDebugging_StagingOnly();
+ }
+ }
+
+private:
+ CInterlockedInt* mCounter;
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// 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(); }
+
+ //------------------------------------------------------
+ // 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 // !_XBOX
+#endif // _WIN64
+ byte m_CriticalSection[TT_SIZEOF_CRITICALSECTION];
+#elif defined(POSIX)
+ pthread_mutex_t m_Mutex;
+ pthread_mutexattr_t m_Attr;
+#else
+#error
+#endif
+
+#ifdef THREAD_MUTEX_TRACING_SUPPORTED
+ // Debugging (always here 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 long *)&m_ownerID, (long)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 );
+ }
+ }
+
+#ifdef WIN32
+ bool TryLock() const volatile { return (const_cast<CThreadFastMutex *>(this))->TryLock(); }
+ void Lock(unsigned nSpinSleepTime = 1 ) const volatile { (const_cast<CThreadFastMutex *>(this))->Lock( nSpinSleepTime ); }
+ void Unlock() const volatile { (const_cast<CThreadFastMutex *>(this))->Unlock(); }
+#endif
+ // 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;
+};
+
+#ifdef COMPILER_CLANG
+# pragma clang diagnostic push
+# pragma clang diagnostic ignored "-Wunused-private-field"
+#endif // Q_CC_CLANG
+
+class ALIGN128 CAlignedThreadFastMutex : public CThreadFastMutex
+{
+public:
+ CAlignedThreadFastMutex()
+ {
+ Assert( (size_t)this % 128 == 0 && sizeof(*this) == 128 );
+ }
+
+private:
+ uint8 pad[128-sizeof(CThreadFastMutex)];
+} ALIGN128_POST;
+
+#ifdef COMPILER_CLANG
+# pragma clang diagnostic pop
+#endif
+
+#else
+typedef CThreadMutex 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, const char* pMutexName, const char* pFilename, int nLineNum, uint64 minReportDurationUs )
+ : m_lock( const_cast< typename V_remove_const< MUTEX_TYPE >::type & >( lock ) )
+ , m_pMutexName( pMutexName )
+ , m_pFilename( pFilename )
+ , m_nLineNum( nLineNum )
+ , m_bOwned( true )
+ {
+ tmTryLockEx( TELEMETRY_LEVEL0, &m_uLockMatcher, minReportDurationUs, pFilename, nLineNum, &m_lock, pMutexName );
+ m_lock.Lock();
+ tmEndTryLockEx( TELEMETRY_LEVEL0, m_uLockMatcher, pFilename, nLineNum, &m_lock, TMLR_SUCCESS );
+ tmSetLockStateEx( TELEMETRY_LEVEL0, pFilename, nLineNum, &m_lock, TMLS_LOCKED, pMutexName );
+ }
+
+ FORCEINLINE CAutoLockT<MUTEX_TYPE>( CAutoLockT<MUTEX_TYPE> && rhs )
+ : m_lock( const_cast< typename V_remove_const< MUTEX_TYPE >::type &>( rhs.m_lock ) )
+ {
+ m_pMutexName = rhs.m_pMutexName;
+ m_pFilename = rhs.m_pFilename;
+ m_nLineNum = rhs.m_nLineNum;
+ #ifdef RAD_TELEMETRY_ENABLED
+ m_uLockMatcher = rhs.m_uLockMatcher;
+ #endif
+ m_bOwned = true;
+ rhs.m_bOwned = false;
+ }
+
+ FORCEINLINE ~CAutoLockT()
+ {
+ if ( m_bOwned )
+ {
+ m_lock.Unlock();
+ tmSetLockStateEx( TELEMETRY_LEVEL0, m_pFilename, m_nLineNum, &m_lock, TMLS_RELEASED, m_pMutexName );
+ }
+ }
+
+private:
+ typename V_remove_const< MUTEX_TYPE >::type &m_lock;
+ const char* m_pMutexName;
+ const char* m_pFilename;
+ int m_nLineNum;
+ bool m_bOwned; // Did owenership of the lock pass to another instance?
+
+#ifdef RAD_TELEMETRY_ENABLED
+ TmU64 m_uLockMatcher;
+#endif
+
+ // Disallow copying
+ CAutoLockT<MUTEX_TYPE>( const CAutoLockT<MUTEX_TYPE> & );
+ CAutoLockT<MUTEX_TYPE> &operator=( const CAutoLockT<MUTEX_TYPE> & );
+
+ // No move assignment because no default construction.
+ CAutoLockT<MUTEX_TYPE> &operator=( CAutoLockT<MUTEX_TYPE> && );
+};
+
+typedef CAutoLockT<CThreadMutex> CAutoLock;
+
+template < typename MUTEX_TYPE >
+inline CAutoLockT<MUTEX_TYPE> make_auto_lock( MUTEX_TYPE& lock, const char* pMutexname, const char* pFilename, int nLineNum, int nMinReportDurationUs = 1 )
+{
+ return CAutoLockT<MUTEX_TYPE>( lock, pMutexname, pFilename, nLineNum, nMinReportDurationUs );
+}
+
+//---------------------------------------------------------
+
+#define AUTO_LOCK( mutex ) \
+ auto UNIQUE_ID = make_auto_lock( mutex, #mutex, __FILE__, __LINE__ );
+
+#define AUTO_LOCK_D( mutex, minDurationUs ) \
+ auto UNIQUE_ID = make_auto_lock( mutex, #mutex, __FILE__, __LINE__, minDurationUs );
+
+#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.
+//
+//-----------------------------------------------------------------------------
+
+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 );
+
+protected:
+ CThreadSyncObject();
+ void AssertUseable();
+
+#ifdef _WIN32
+ HANDLE m_hSyncObject;
+ bool m_bCreatedHandle;
+#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
+//
+//-----------------------------------------------------------------------------
+
+#if defined( _WIN32 )
+
+//-----------------------------------------------------------------------------
+//
+// CThreadSemaphore
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThreadSemaphore : public CThreadSyncObject
+{
+public:
+ CThreadSemaphore(long initialValue, long maxValue);
+
+ //-----------------------------------------------------
+ // Increases the count of the semaphore object by a specified
+ // amount. Wait() decreases the count by one on return.
+ //-----------------------------------------------------
+ bool Release(long releaseCount = 1, long * pPreviousCount = NULL );
+
+private:
+ CThreadSemaphore(const CThreadSemaphore &);
+ CThreadSemaphore &operator=(const CThreadSemaphore &);
+};
+
+
+//-----------------------------------------------------------------------------
+//
+// 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
+
+
+class PLATFORM_CLASS CThreadEvent : public CThreadSyncObject
+{
+public:
+ CThreadEvent( bool fManualReset = false );
+#ifdef WIN32
+ 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();
+
+ bool Wait( uint32 dwTimeout = TT_INFINITE );
+
+private:
+ CThreadEvent( const CThreadEvent & );
+ CThreadEvent &operator=( const CThreadEvent & );
+};
+
+// Hard-wired manual event for use in array declarations
+class CThreadManualEvent : public CThreadEvent
+{
+public:
+ CThreadManualEvent()
+ : CThreadEvent( true )
+ {
+ }
+};
+
+inline int ThreadWaitForEvents( int nEvents, CThreadEvent * const *pEvents, bool bWaitAll = true, unsigned timeout = TT_INFINITE )
+{
+#ifdef POSIX
+ Assert( nEvents == 1);
+ if ( pEvents[0]->Wait( timeout ) )
+ return WAIT_OBJECT_0;
+ else
+ return WAIT_TIMEOUT;
+#else
+ HANDLE handles[64];
+ for ( int i = 0; i < min( nEvents, (int)ARRAYSIZE(handles) ); i++ )
+ handles[i] = pEvents[i]->GetHandle();
+ return ThreadWaitForObjects( nEvents, handles, bWaitAll, timeout );
+#endif
+}
+
+//-----------------------------------------------------------------------------
+//
+// 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
+//
+//-----------------------------------------------------------------------------
+
+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:
+ struct LockInfo_t
+ {
+ uint32 m_writerId;
+ int m_nReaders;
+ };
+
+ 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;
+
+//-----------------------------------------------------------------------------
+//
+// A thread wrapper similar to a Java thread.
+//
+//-----------------------------------------------------------------------------
+
+class PLATFORM_CLASS CThread
+{
+public:
+ CThread();
+ virtual ~CThread();
+
+ //-----------------------------------------------------
+
+ const char *GetName();
+ void SetName( const char * );
+
+ size_t CalcStackDepth( void *pStackVariable ) { return ((byte *)m_pStackBase - (byte *)pStackVariable); }
+
+ //-----------------------------------------------------
+ // Functions for the other threads
+ //-----------------------------------------------------
+
+ // Start thread running - error if already running
+ virtual bool Start( unsigned nBytesStack = 0 );
+
+ // 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 );
+
+#ifdef _WIN32
+ // Access the thread handle directly
+ HANDLE GetThreadHandle();
+ uint GetThreadId();
+#elif defined( LINUX )
+ 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 );
+
+ // Request a thread to suspend, this must ONLY be called from the thread itself, not the main thread
+ // This suspend variant causes the thread in question to suspend at a known point in its execution
+ // which means you don't risk the global deadlocks/hangs potentially caused by the raw Suspend() call
+ void SuspendCooperative();
+
+ // Resume a previously suspended thread from the Cooperative call
+ void ResumeCooperative();
+
+ // wait for a thread to execute its SuspendCooperative call
+ void BWaitForThreadSuspendCooperative();
+
+#ifndef LINUX
+ // forcefully Suspend a thread
+ unsigned int Suspend();
+
+ // forcefully Resume a previously suspended thread
+ unsigned int Resume();
+#endif
+
+ // 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.
+ 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 is about to exit, by the about-to-exit thread.
+ virtual void OnExit();
+
+ // Called after OnExit when a thread finishes or is killed. Not virtual because no inherited classes
+ // override it and we don't want to change the vtable from the published SDK version.
+ void Cleanup();
+
+ bool WaitForCreateComplete( CThreadEvent *pEvent );
+
+ // "Virtual static" facility
+ typedef unsigned (__stdcall *ThreadProc_t)( void * );
+ virtual ThreadProc_t GetThreadProc();
+ virtual bool IsThreadRunning();
+
+ CThreadMutex m_Lock;
+
+#ifdef WIN32
+ ThreadHandle_t GetThreadID() const { return (ThreadHandle_t)m_hThread; }
+#else
+ ThreadId_t GetThreadID() const { return (ThreadId_t)m_threadId; }
+#endif
+
+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;
+ };
+
+ static unsigned __stdcall ThreadProc( void * pv );
+
+ // 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(POSIX)
+ pthread_t m_threadId;
+#endif
+ CInterlockedInt m_nSuspendCount;
+ CThreadEvent m_SuspendEvent;
+ CThreadEvent m_SuspendEventSignal;
+ int m_result;
+ char m_szName[32];
+ void * m_pStackBase;
+ unsigned m_flags;
+};
+
+//-----------------------------------------------------------------------------
+//
+// A helper class to let you sleep a thread for memory validation, you need to handle
+// m_bSleepForValidate in your ::Run() call and set m_bSleepingForValidate when sleeping
+//
+//-----------------------------------------------------------------------------
+class PLATFORM_CLASS CValidatableThread : public CThread
+{
+public:
+ CValidatableThread()
+ {
+ m_bSleepForValidate = false;
+ m_bSleepingForValidate = false;
+ }
+
+#ifdef DBGFLAG_VALIDATE
+ virtual void SleepForValidate() { m_bSleepForValidate = true; }
+ bool BSleepingForValidate() { return m_bSleepingForValidate; }
+ virtual void WakeFromValidate() { m_bSleepForValidate = false; }
+#endif
+protected:
+ bool m_bSleepForValidate;
+ bool m_bSleepingForValidate;
+};
+
+//-----------------------------------------------------------------------------
+// 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 CFunctor;
+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, CFunctor *pParamFunctor = NULL );
+
+ // 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, CFunctor **ppParamFunctor = 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();
+ // Find out what the request was
+ unsigned GetCallParam( CFunctor **ppParamFunctor = NULL ) const;
+
+ // Boost the worker thread to the master thread, if worker thread is lesser, return old priority
+ int BoostPriority();
+
+protected:
+#ifndef _WIN32
+#define __stdcall
+#endif
+ typedef uint32 (__stdcall *WaitFunc_t)( int nEvents, CThreadEvent * const *pEvents, int bWaitAll, uint32 timeout );
+
+ int Call( unsigned, unsigned timeout, bool fBoost, WaitFunc_t = NULL, CFunctor *pParamFunctor = NULL );
+ int WaitForReply( unsigned timeout, WaitFunc_t );
+
+private:
+ CWorkerThread( const CWorkerThread & );
+ CWorkerThread &operator=( const CWorkerThread & );
+
+ CThreadEvent m_EventSend;
+ CThreadEvent m_EventComplete;
+
+ unsigned m_Param;
+ CFunctor *m_pParamFunctor;
+ 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 _WIN32
+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
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Lock()
+{
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+ uint thisThreadID = ThreadGetCurrentId();
+ if ( m_bTrace && m_currentOwnerID && ( m_currentOwnerID != thisThreadID ) )
+ Msg( "Thread %u about to wait for lock %p owned by %u\n", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ #endif
+
+ VCRHook_EnterCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+
+ #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( "Thread %u now owns lock %p\n", m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ }
+ m_lockCount++;
+ #endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::Unlock()
+{
+ #ifdef THREAD_MUTEX_TRACING_ENABLED
+ AssertMsg( m_lockCount >= 1, "Invalid unlock of thread lock" );
+ m_lockCount--;
+ if (m_lockCount == 0)
+ {
+ if ( m_bTrace )
+ Msg( "Thread %u releasing lock %p\n", m_currentOwnerID, (CRITICAL_SECTION *)&m_CriticalSection );
+ m_currentOwnerID = 0;
+ }
+ #endif
+ LeaveCriticalSection((CRITICAL_SECTION *)&m_CriticalSection);
+}
+
+//---------------------------------------------------------
+
+inline bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+ if (ThreadGetCurrentId() == m_currentOwnerID)
+ return true;
+ AssertMsg3( 0, "Expected thread %u as owner of lock %p, but %u owns", ThreadGetCurrentId(), (CRITICAL_SECTION *)&m_CriticalSection, m_currentOwnerID );
+ return false;
+#else
+ return true;
+#endif
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace( bool bTrace )
+{
+#ifdef THREAD_MUTEX_TRACING_ENABLED
+ m_bTrace = bTrace;
+#endif
+}
+
+//---------------------------------------------------------
+
+#elif defined(POSIX)
+
+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 bool CThreadMutex::AssertOwnedByCurrentThread()
+{
+ return true;
+}
+
+//---------------------------------------------------------
+
+inline void CThreadMutex::SetTrace(bool fTrace)
+{
+}
+
+#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
+//
+//-----------------------------------------------------------------------------
+
+inline bool CThreadSpinRWLock::AssignIf( const LockInfo_t &newValue, const LockInfo_t &comperand )
+{
+ return ThreadInterlockedAssignIf64( (int64 *)&m_lockInfo, *((int64 *)&newValue), *((int64 *)&comperand) );
+}
+
+inline 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 };
+ const bool bSuccess = AssignIf( newValue, oldValue );
+#if defined(_X360)
+ if ( bSuccess )
+ {
+ // X360TBD: Serious perf implications. Not Yet. __sync();
+ }
+#endif
+ return bSuccess;
+}
+
+inline bool CThreadSpinRWLock::TryLockForWrite()
+{
+ m_nWriters++;
+ if ( !TryLockForWrite( ThreadGetCurrentId() ) )
+ {
+ m_nWriters--;
+ return false;
+ }
+ return true;
+}
+
+inline 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;
+
+ oldValue.m_nReaders = m_lockInfo.m_nReaders;
+ oldValue.m_writerId = 0;
+ newValue.m_nReaders = oldValue.m_nReaders + 1;
+ newValue.m_writerId = 0;
+
+ const bool bSuccess = AssignIf( newValue, oldValue );
+#if defined(_X360)
+ if ( bSuccess )
+ {
+ // X360TBD: Serious perf implications. Not Yet. __sync();
+ }
+#endif
+ return bSuccess;
+}
+
+inline void CThreadSpinRWLock::LockForWrite()
+{
+ const uint32 threadId = ThreadGetCurrentId();
+
+ m_nWriters++;
+
+ if ( !TryLockForWrite( threadId ) )
+ {
+ ThreadPause();
+ SpinLockForWrite( threadId );
+ }
+}
+
+// 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
+
+#endif // THREADTOOLS_H
diff --git a/public/tier0/tmapi_dummy.h b/public/tier0/tmapi_dummy.h
new file mode 100644
index 0000000..8a6aebc
--- /dev/null
+++ b/public/tier0/tmapi_dummy.h
@@ -0,0 +1,84 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+// This is the null header file used to remove Telemetry calls.
+
+#define TMERR_DISABLED 1
+#define TMPRINTF_TOKEN_NONE 0
+
+#define tmGetSessionName(...)
+#define tmEndTryLock(...)
+#define tmEndTryLockEx(...)
+#define tmSetLockState(...)
+#define tmSetLockStateEx(...)
+#define tmSetLockStateMinTime(...) 0
+#define tmSetLockStateMinTimeEx(...) 0
+#define tmSignalLockCount(...)
+
+#define tmCheckVersion(...) 0
+#define tmGetCallStack(...) 0
+#define tmSendCallStack( ... ) TMPRINTF_TOKEN_NONE
+#define tmGetCallStackR(...) 0
+#define tmSendCallStackR(...) TMPRINTF_TOKEN_NONE
+#define tmSendCallStackWithSkipR(...) TMPRINTF_TOKEN_NONE
+
+#define tmGetVersion(...) 0
+#define tmStartup(...) TMERR_DISABLED
+#define tmGetPlatformInformation(...) TMERR_DISABLED
+#define tmInitializeContext(...) TMERR_DISABLED
+#define tmShutdown(...) TMERR_DISABLED
+
+#define tmEnter(...)
+#define tmEnterEx(...)
+#define tmZone(...)
+#define tmZoneFiltered(...)
+#define tmLeave(...)
+#define tmLeaveEx(...)
+
+#define tmBeginTimeSpan(...)
+#define tmEndTimeSpan(...)
+
+#define tmBeginTimeSpanAt(...)
+#define tmEndTimeSpanAt(...)
+
+#define tmDynamicString(...) ""
+
+#define tmEmitAccumulationZone(...)
+
+#define tmGetStati(...) 0
+
+#define tmSetVariable(...)
+
+#define tmBlob(...)
+#define tmDisjointBlob(...)
+#define tmSetTimelineSectionName(...)
+#define tmThreadName(...)
+#define tmLockName(...)
+#define tmMessage(...)
+#define tmAlloc(...)
+#define tmAllocEx(...)
+
+#define tmTryLock(...)
+#define tmTryLockEx(...)
+
+#define tmPlot(...)
+#define tmPlotF32(...)
+#define tmPlotF64(...)
+#define tmPlotI32(...)
+#define tmPlotU32(...)
+#define tmPlotS32(...)
+#define tmPlotI64(...)
+#define tmPlotU64(...)
+#define tmPlotS64(...)
+
+#define tmPPUGetListener(...) TMERR_DISABLED
+#define tmPPURegisterSPUProgram(...) TMERR_DISABLED
+#define tmSPUBindContextToListener(...)
+#define tmSPUUpdateTime(...)
+#define tmSPUFlushImage(...)
+
+#define NTELEMETRY 1
+
+#define TM_CONTEXT_LITE(val) ((char*)(val))
+#define TM_CONTEXT_FULL(val) ((char*)(val))
+
+typedef char *HTELEMETRY;
+
diff --git a/public/tier0/tslist.h b/public/tier0/tslist.h
new file mode 100644
index 0000000..d6610e0
--- /dev/null
+++ b/public/tier0/tslist.h
@@ -0,0 +1,1004 @@
+//========= Copyright 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
+// Suppress this spurious warning:
+// warning C4700: uninitialized local variable 'oldHead' used
+#pragma warning( push )
+#pragma warning( disable : 4700 )
+#endif
+
+#if defined( USE_NATIVE_SLIST ) && !defined( _X360 )
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/threadtools.h"
+#include "tier0/memalloc.h"
+#include "tier0/memdbgoff.h"
+
+#if defined( _X360 )
+#define USE_NATIVE_SLIST
+#endif
+
+//-----------------------------------------------------------------------------
+
+#if defined( PLATFORM_64BITS )
+
+#define TSLIST_HEAD_ALIGNMENT 16
+#define TSLIST_NODE_ALIGNMENT 16
+inline bool ThreadInterlockedAssignIf64x128( volatile int128 *pDest, const int128 &value, const int128 &comperand )
+ { return ThreadInterlockedAssignIf128( pDest, value, comperand ); }
+#else
+#define TSLIST_HEAD_ALIGNMENT 8
+#define TSLIST_NODE_ALIGNMENT 8
+inline bool ThreadInterlockedAssignIf64x128( volatile int64 *pDest, const int64 value, const int64 comperand )
+ { return ThreadInterlockedAssignIf64( pDest, value, comperand ); }
+#endif
+
+#ifdef _MSC_VER
+#define TSLIST_HEAD_ALIGN DECL_ALIGN(TSLIST_HEAD_ALIGNMENT)
+#define TSLIST_NODE_ALIGN DECL_ALIGN(TSLIST_NODE_ALIGNMENT)
+#define TSLIST_HEAD_ALIGN_POST
+#define TSLIST_NODE_ALIGN_POST
+#elif defined( GNUC )
+#define TSLIST_HEAD_ALIGN
+#define TSLIST_NODE_ALIGN
+#define TSLIST_HEAD_ALIGN_POST DECL_ALIGN(TSLIST_HEAD_ALIGNMENT)
+#define TSLIST_NODE_ALIGN_POST DECL_ALIGN(TSLIST_NODE_ALIGNMENT)
+#elif defined( _PS3 )
+#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
+
+#else
+#error
+#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 TSLIST_HEAD_ALIGN 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 VALVE_BIG_ENDIAN
+ int16 Sequence;
+ int16 Depth;
+ #else
+ int16 Depth;
+ int16 Sequence;
+ #endif
+#ifdef PLATFORM_64BITS
+ int32 Padding;
+#endif
+ } value;
+
+ struct Value32_t
+ {
+ TSLNodeBase_t *Next_do_not_use_me;
+ int32 DepthAndSequence;
+ } value32;
+
+#ifdef PLATFORM_64BITS
+ int128 value64x128;
+#else
+ int64 value64x128;
+#endif
+} TSLIST_HEAD_ALIGN_POST;
+
+#endif
+
+//-------------------------------------
+class CTSListBase
+{
+public:
+
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size )
+ {
+ CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
+ return pNode;
+ }
+
+ static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
+ {
+ CTSListBase *pNode = (CTSListBase *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
+ return pNode;
+ }
+
+ static void operator delete( void *p)
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+private:
+ // These ain't gonna work
+ static void * operator new[] ( size_t size );
+ static void operator delete [] ( void *p);
+
+public:
+
+ CTSListBase()
+ {
+ if ( ((size_t)&m_Head) % TSLIST_HEAD_ALIGNMENT != 0 )
+ {
+ Error( "CTSListBase: Misaligned list\n" );
+ DebuggerBreak();
+ }
+
+#ifdef USE_NATIVE_SLIST
+ InitializeSListHead( &m_Head );
+#elif defined(PLATFORM_64BITS)
+ m_Head.value64x128 = int128_zero();
+#else
+ m_Head.value64x128 = (int64)0;
+#endif
+ }
+
+ ~CTSListBase()
+ {
+ Detach();
+ }
+
+ TSLNodeBase_t *Push( TSLNodeBase_t *pNode )
+ {
+#ifdef _DEBUG
+ if ( (size_t)pNode % TSLIST_NODE_ALIGNMENT != 0 )
+ {
+ Error( "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
+
+#ifdef PLATFORM_64BITS
+ newHead.value.Padding = 0;
+#endif
+ for (;;)
+ {
+ oldHead.value64x128 = m_Head.value64x128;
+ pNode->Next = oldHead.value.Next;
+ newHead.value.Next = pNode;
+
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence + 0x10001;
+
+
+ if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
+ {
+ 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;
+
+#ifdef PLATFORM_64BITS
+ newHead.value.Padding = 0;
+#endif
+ for (;;)
+ {
+ oldHead.value64x128 = m_Head.value64x128;
+ if ( !oldHead.value.Next )
+ return NULL;
+
+ newHead.value.Next = oldHead.value.Next->Next;
+ newHead.value32.DepthAndSequence = oldHead.value32.DepthAndSequence - 1;
+
+
+ if ( ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) )
+ {
+ #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;
+
+#ifdef PLATFORM_64BITS
+ newHead.value.Padding = 0;
+#endif
+ do
+ {
+ ThreadPause();
+
+ oldHead.value64x128 = m_Head.value64x128;
+ 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( !ThreadInterlockedAssignIf64x128( &m_Head.value64x128, newHead.value64x128, oldHead.value64x128 ) );
+
+ 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()
+ {
+ Purge();
+ }
+
+ void Purge()
+ {
+ 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;
+
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size )
+ {
+ Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, __FILE__, __LINE__ );
+ return pNode;
+ }
+
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
+ {
+ Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_NODE_ALIGNMENT, pFileName, nLine );
+ return pNode;
+ }
+
+ static void operator delete( void *p)
+ {
+ MemAlloc_FreeAligned( p );
+ }
+ static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ } 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>
+class TSLIST_HEAD_ALIGN CTSQueue
+{
+public:
+
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size )
+ {
+ CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
+ return pNode;
+ }
+
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
+ {
+ CTSQueue *pNode = (CTSQueue *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
+ return pNode;
+ }
+
+ static void operator delete( void *p)
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+private:
+ // These ain't gonna work
+ static void * operator new[] ( size_t size ) throw()
+ {
+ return NULL;
+ }
+
+ static void operator delete [] ( void *p)
+ {
+ }
+
+public:
+
+ struct TSLIST_NODE_ALIGN Node_t
+ {
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size )
+ {
+ Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
+ return pNode;
+ }
+
+ static void * operator new( size_t size, int nBlockUse, const char *pFileName, int nLine )
+ {
+ Node_t *pNode = (Node_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, pFileName, nLine );
+ return pNode;
+ }
+
+ static void operator delete( void *p)
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ static void operator delete( void *p, int nBlockUse, const char *pFileName, int nLine )
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ Node_t() {}
+ Node_t( const T &init ) : elem( init ) {}
+
+ Node_t *pNext;
+ T elem;
+ } TSLIST_NODE_ALIGN_POST;
+
+ union TSLIST_HEAD_ALIGN NodeLink_t
+ {
+ // override new/delete so we can guarantee 8-byte aligned allocs
+ static void * operator new( size_t size )
+ {
+ NodeLink_t *pNode = (NodeLink_t *)MemAlloc_AllocAligned( size, TSLIST_HEAD_ALIGNMENT, __FILE__, __LINE__ );
+ return pNode;
+ }
+
+ static void operator delete( void *p)
+ {
+ MemAlloc_FreeAligned( p );
+ }
+
+ struct Value_t
+ {
+ Node_t *pNode;
+ intp sequence;
+ } value;
+
+#ifdef PLATFORM_64BITS
+ int128 value64x128;
+#else
+ int64 value64x128;
+#endif
+ } 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() )
+ {
+ ValidateQueue();
+ }
+
+ Node_t *pNode;
+ while ( ( pNode = Pop() ) != NULL )
+ {
+ delete pNode;
+ }
+
+ while ( ( 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() )
+ {
+ ValidateQueue();
+ }
+
+ Node_t *pNode;
+ while ( ( pNode = Pop() ) != NULL )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+ }
+
+ bool ValidateQueue()
+ {
+ if ( IsDebug() )
+ {
+ bool bResult = true;
+ int nNodes = 0;
+ if ( m_Tail.value.pNode->pNext != End() )
+ {
+ DebuggerBreakIfDebugging();
+ bResult = false;
+ }
+
+ 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;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ 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 intp * volatile pHeadSequence = &m_Head.value.sequence;
+ Node_t * volatile * pTailNode = &pTail->value.pNode;
+
+ NodeLink_t head;
+ NodeLink_t newHead;
+ Node_t *pNext;
+ intp 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;
+
+ // Checking pNext only to force optimizer to not reorder the assignment
+ // to pNext and the compare of the sequence
+ if ( !pNext || head.value.sequence != *pHeadSequence )
+ continue;
+
+ 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 );
+ continue;
+ }
+
+ 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 )
+ {
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ }
+
+ void PushItem( const T &init )
+ {
+ Node_t *pNode = (Node_t *)m_FreeNodes.Pop();
+ if ( pNode )
+ {
+ 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;
+ m_FreeNodes.Push( (TSLNodeBase_t *)pNode );
+ return true;
+ }
+
+ int Count() const
+ {
+ return m_Count;
+ }
+
+private:
+ Node_t *End() { return (Node_t *)this; } // just need a unique signifier
+
+ 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 ThreadInterlockedAssignIf64x128( &pLink->value64x128, value.value64x128, comperand.value64x128 );
+ }
+
+ NodeLink_t m_Head;
+ NodeLink_t m_Tail;
+
+ CInterlockedInt m_Count;
+
+ CTSListBase m_FreeNodes;
+} TSLIST_NODE_ALIGN_POST;
+
+#if defined( _WIN32 )
+// Suppress this spurious warning:
+// warning C4700: uninitialized local variable 'oldHead' used
+#pragma warning( pop )
+#endif
+
+#endif // TSLIST_H
diff --git a/public/tier0/type_traits.h b/public/tier0/type_traits.h
new file mode 100644
index 0000000..6459de4
--- /dev/null
+++ b/public/tier0/type_traits.h
@@ -0,0 +1,32 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: functionality that is provided in C++11 type_traits, which
+// currently isn't supported by the OSX compiler. Sadness.
+//
+//=============================================================================
+#pragma once
+
+template <class T>
+struct V_remove_const
+{
+ typedef T type;
+};
+
+template <class T>
+struct V_remove_const<const T>
+{
+ typedef T type;
+};
+
+template <class T>
+struct V_remove_const<const T[]>
+{
+ typedef T type;
+};
+
+template <class T, unsigned int N>
+struct V_remove_const<const T[N]>
+{
+ typedef T type;
+};
+
diff --git a/public/tier0/validator.h b/public/tier0/validator.h
new file mode 100644
index 0000000..6af0f51
--- /dev/null
+++ b/public/tier0/validator.h
@@ -0,0 +1,73 @@
+//========= Copyright 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/public/tier0/valobject.h b/public/tier0/valobject.h
new file mode 100644
index 0000000..c139e9e
--- /dev/null
+++ b/public/tier0/valobject.h
@@ -0,0 +1,72 @@
+//========= Copyright 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/public/tier0/valve_minmax_off.h b/public/tier0/valve_minmax_off.h
new file mode 100644
index 0000000..633a378
--- /dev/null
+++ b/public/tier0/valve_minmax_off.h
@@ -0,0 +1,7 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#ifdef min
+ #undef min
+#endif
+#ifdef max
+ #undef max
+#endif
diff --git a/public/tier0/valve_minmax_on.h b/public/tier0/valve_minmax_on.h
new file mode 100644
index 0000000..738eabc
--- /dev/null
+++ b/public/tier0/valve_minmax_on.h
@@ -0,0 +1,9 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+#if !defined(POSIX)
+#ifndef min
+ #define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef max
+ #define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#endif
diff --git a/public/tier0/valve_off.h b/public/tier0/valve_off.h
new file mode 100644
index 0000000..796408e
--- /dev/null
+++ b/public/tier0/valve_off.h
@@ -0,0 +1,30 @@
+//========= Copyright 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
diff --git a/public/tier0/valve_on.h b/public/tier0/valve_on.h
new file mode 100644
index 0000000..ffc9b89
--- /dev/null
+++ b/public/tier0/valve_on.h
@@ -0,0 +1,31 @@
+//========= Copyright 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
diff --git a/public/tier0/vcr_shared.h b/public/tier0/vcr_shared.h
new file mode 100644
index 0000000..d2d5ac7
--- /dev/null
+++ b/public/tier0/vcr_shared.h
@@ -0,0 +1,54 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VCR_SHARED_H
+#define VCR_SHARED_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+
+#define VCRFILE_VERSION 2
+
+
+// Identifiers for the things we record. When playing back, these things should
+// be asked for in the exact same order (otherwise, the engine isn't making all
+// the calls in the same order).
+typedef enum
+{
+ VCREvent_Sys_FloatTime=0,
+ VCREvent_recvfrom,
+ VCREvent_SyncToken,
+ VCREvent_GetCursorPos,
+ VCREvent_SetCursorPos,
+ VCREvent_ScreenToClient,
+ VCREvent_Cmd_Exec,
+ VCREvent_CmdLine,
+ VCREvent_RegOpenKeyEx,
+ VCREvent_RegSetValueEx,
+ VCREvent_RegQueryValueEx,
+ VCREvent_RegCreateKeyEx,
+ VCREvent_RegCloseKey,
+ VCREvent_PeekMessage,
+ VCREvent_GameMsg,
+ VCREvent_GetNumberOfConsoleInputEvents,
+ VCREvent_ReadConsoleInput,
+ VCREvent_GetKeyState,
+ VCREvent_recv,
+ VCREvent_send,
+ VCREvent_Generic,
+ VCREvent_CreateThread,
+ VCREvent_WaitForSingleObject,
+ VCREvent_EnterCriticalSection,
+ VCREvent_Time,
+ VCREvent_LocalTime,
+ VCREvent_GenericString,
+ VCREvent_NUMEVENTS
+} VCREvent;
+
+
+#endif // VCR_SHARED_H
diff --git a/public/tier0/vcrmode.h b/public/tier0/vcrmode.h
new file mode 100644
index 0000000..2af8a60
--- /dev/null
+++ b/public/tier0/vcrmode.h
@@ -0,0 +1,306 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: VCR mode records a client's game and allows you to
+// play it back and reproduce it exactly. When playing it back, nothing
+// is simulated on the server, but all server packets are recorded.
+//
+// Most of the VCR mode functionality is accomplished through hooks
+// called at various points in the engine.
+//
+// $NoKeywords: $
+//===========================================================================//
+#ifndef VCRMODE_H
+#define VCRMODE_H
+
+#ifdef _WIN32
+#include <process.h>
+#endif
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "tier0/platform.h"
+#include "tier0/vcr_shared.h"
+#include "tier0/dbg.h"
+
+#ifdef POSIX
+DBG_INTERFACE const char *BuildCmdLine( int argc, char **argv, bool fAddSteam = true );
+tchar *GetCommandLine();
+#endif
+
+#ifdef _X360
+#define NO_VCR 1
+#endif
+
+
+// Enclose lines of code in this if you don't want anything in them written to or read from the VCR file.
+#ifndef NO_VCR
+#define NOVCR(x) \
+{\
+ VCRSetEnabled(0);\
+ x;\
+ VCRSetEnabled(1);\
+}
+#else
+#define NOVCR(x) \
+{\
+ x;\
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct InputEvent_t;
+
+
+//-----------------------------------------------------------------------------
+// Definitions.
+//-----------------------------------------------------------------------------
+enum VCRMode_t
+{
+ VCR_Invalid=-1,
+ VCR_Disabled=0,
+ VCR_Record,
+ VCR_Playback
+};
+
+
+//-----------------------------------------------------------------------------
+// Functions.
+//-----------------------------------------------------------------------------
+abstract_class IVCRHelpers
+{
+public:
+ virtual void ErrorMessage( const tchar *pMsg ) = 0;
+ virtual void* GetMainWindow() = 0;
+};
+
+
+// Used by the vcrtrace program.
+abstract_class IVCRTrace
+{
+public:
+ virtual VCREvent ReadEvent() = 0;
+ virtual void Read( void *pDest, int size ) = 0;
+};
+
+typedef struct VCR_s
+{
+ // Start VCR record or play.
+ int (*Start)( tchar const *pFilename, bool bRecord, IVCRHelpers *pHelpers );
+ void (*End)();
+
+ // Used by the VCR trace app.
+ IVCRTrace* (*GetVCRTraceInterface)();
+
+ // Get the current mode the VCR is in.
+ VCRMode_t (*GetMode)();
+
+ // This can be used to block out areas of code that are unpredictable (like things triggered by WM_TIMER messages).
+ // Note: this enables/disables VCR mode usage on a PER-THREAD basis. The assumption is that you're marking out
+ // specific sections of code that you don't want to use VCR mode inside of, but you're not intending to
+ // stop all the other threads from using VCR mode.
+ void (*SetEnabled)(int bEnabled);
+
+ // This can be called any time to put in a debug check to make sure things are synchronized.
+ void (*SyncToken)(tchar const *pToken);
+
+ // Hook for Sys_FloatTime().
+ double (*Hook_Sys_FloatTime)(double time);
+
+ // Note: this makes no guarantees about msg.hwnd being the same on playback. If it needs to be, then we need to add
+ // an ID system for Windows and store the ID like in Goldsrc.
+ int (*Hook_PeekMessage)(
+ struct tagMSG *msg,
+ void *hWnd,
+ unsigned int wMsgFilterMin,
+ unsigned int wMsgFilterMax,
+ unsigned int wRemoveMsg
+ );
+
+ // Call this to record game messages.
+ void (*Hook_RecordGameMsg)( const InputEvent_t &event );
+ void (*Hook_RecordEndGameMsg)();
+
+ // Call this to playback game messages until it returns false.
+ bool (*Hook_PlaybackGameMsg)( InputEvent_t *pEvent );
+
+ // Hook for recvfrom() calls. This replaces the recvfrom() call.
+ int (*Hook_recvfrom)(int s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen);
+
+ void (*Hook_GetCursorPos)(struct tagPOINT *pt);
+ void (*Hook_ScreenToClient)(void *hWnd, struct tagPOINT *pt);
+
+ void (*Hook_Cmd_Exec)(tchar **f);
+
+ tchar* (*Hook_GetCommandLine)();
+
+ // Registry hooks.
+ long (*Hook_RegOpenKeyEx)( void *hKey, const tchar *lpSubKey, unsigned long ulOptions, unsigned long samDesired, void *pHKey );
+ long (*Hook_RegSetValueEx)(void *hKey, tchar const *lpValueName, unsigned long Reserved, unsigned long dwType, uint8 const *lpData, unsigned long cbData);
+ long (*Hook_RegQueryValueEx)(void *hKey, tchar const *lpValueName, unsigned long *lpReserved, unsigned long *lpType, uint8 *lpData, unsigned long *lpcbData);
+ long (*Hook_RegCreateKeyEx)(void *hKey, tchar const *lpSubKey, unsigned long Reserved, tchar *lpClass, unsigned long dwOptions, unsigned long samDesired, void *lpSecurityAttributes, void *phkResult, unsigned long *lpdwDisposition);
+ void (*Hook_RegCloseKey)(void *hKey);
+
+ // hInput is a HANDLE.
+ int (*Hook_GetNumberOfConsoleInputEvents)( void *hInput, unsigned long *pNumEvents );
+
+ // hInput is a HANDLE.
+ // pRecs is an INPUT_RECORD pointer.
+ int (*Hook_ReadConsoleInput)( void *hInput, void *pRecs, int nMaxRecs, unsigned long *pNumRead );
+
+
+ // This calls time() then gives you localtime()'s result.
+ void (*Hook_LocalTime)( struct tm *today );
+
+ short (*Hook_GetKeyState)( int nVirtKey );
+
+ // TCP calls.
+ int (*Hook_recv)( int s, char *buf, int len, int flags );
+ int (*Hook_send)( int s, const char *buf, int len, int flags );
+
+ // These can be used to add events without having to modify VCR mode.
+ // pEventName is used for verification to make sure it's playing back correctly.
+ // If pEventName is null, then verification is not performed.
+ void (*GenericRecord)( const tchar *pEventName, const void *pData, int len );
+
+
+ // Returns the number of bytes written in the generic event.
+ // If bForceLenSame is true, then it will error out unless the value in the VCR file is the same as maxLen.
+ int (*GenericPlayback)( const tchar *pEventName, void *pOutData, int maxLen, bool bForceLenSame );
+
+ // If you just want to record and playback a value and not worry about whether or not you're
+ // recording or playing back, use this. It also will do nothing if you're not recording or playing back.
+ //
+ // NOTE: also see GenericValueVerify, which allows you to have it VERIFY that pData's contents are the same upon playback
+ // (rather than just copying whatever is in the VCR file into pData).
+ void (*GenericValue)( const tchar *pEventName, void *pData, int maxLen );
+
+ // Get the current percent (0.0 - 1.0) that it's played back through the file (only valid in playback).
+ double (*GetPercentCompleted)();
+
+ // If you use this, then any VCR stuff the thread does will work with VCR mode.
+ // This mirrors the Windows API CreateThread function and returns a HANDLE the same way.
+ void* (*Hook_CreateThread)(
+ void *lpThreadAttributes,
+ unsigned long dwStackSize,
+ void *lpStartAddress,
+ void *lpParameter,
+ unsigned long dwCreationFlags,
+ unsigned long *lpThreadID );
+
+ unsigned long (*Hook_WaitForSingleObject)(
+ void *handle,
+ unsigned long dwMilliseconds );
+
+ void (*Hook_EnterCriticalSection)( void *pCS );
+
+ void (*Hook_Time)( long *pTime );
+
+ // String value. Playback just verifies that the incoming string is the same as it was when recording.
+ void (*GenericString)( const char *pEventName, const char *pString );
+
+ // Works like GenericValue, except upon playback it will verify that pData's contents are the same as it was during recording.
+ void (*GenericValueVerify)( const tchar *pEventName, const void *pData, int maxLen );
+
+ unsigned long (*Hook_WaitForMultipleObjects)( uint32 nHandles, const void **pHandles, int bWaitAll, uint32 timeout );
+
+} VCR_t;
+
+#ifndef NO_VCR
+
+// In the launcher, this is created by vcrmode.c.
+// In the engine, this is set when the launcher initializes its DLL.
+PLATFORM_INTERFACE VCR_t *g_pVCR;
+
+#endif
+
+
+#ifndef NO_VCR
+#define VCRStart g_pVCR->Start
+#define VCREnd g_pVCR->End
+#define VCRGetVCRTraceInterface g_pVCR->GetVCRTraceInterface
+#define VCRGetMode g_pVCR->GetMode
+#define VCRSetEnabled g_pVCR->SetEnabled
+#define VCRSyncToken g_pVCR->SyncToken
+#define VCRGenericString g_pVCR->GenericString
+#define VCRGenericValueVerify g_pVCR->GenericValueVerify
+#define VCRHook_Sys_FloatTime g_pVCR->Hook_Sys_FloatTime
+#define VCRHook_PeekMessage g_pVCR->Hook_PeekMessage
+#define VCRHook_RecordGameMsg g_pVCR->Hook_RecordGameMsg
+#define VCRHook_RecordEndGameMsg g_pVCR->Hook_RecordEndGameMsg
+#define VCRHook_PlaybackGameMsg g_pVCR->Hook_PlaybackGameMsg
+#define VCRHook_recvfrom g_pVCR->Hook_recvfrom
+#define VCRHook_GetCursorPos g_pVCR->Hook_GetCursorPos
+#define VCRHook_ScreenToClient g_pVCR->Hook_ScreenToClient
+#define VCRHook_Cmd_Exec g_pVCR->Hook_Cmd_Exec
+#define VCRHook_GetCommandLine g_pVCR->Hook_GetCommandLine
+#define VCRHook_RegOpenKeyEx g_pVCR->Hook_RegOpenKeyEx
+#define VCRHook_RegSetValueEx g_pVCR->Hook_RegSetValueEx
+#define VCRHook_RegQueryValueEx g_pVCR->Hook_RegQueryValueEx
+#define VCRHook_RegCreateKeyEx g_pVCR->Hook_RegCreateKeyEx
+#define VCRHook_RegCloseKey g_pVCR->Hook_RegCloseKey
+#define VCRHook_GetNumberOfConsoleInputEvents g_pVCR->Hook_GetNumberOfConsoleInputEvents
+#define VCRHook_ReadConsoleInput g_pVCR->Hook_ReadConsoleInput
+#define VCRHook_LocalTime g_pVCR->Hook_LocalTime
+#define VCRHook_GetKeyState g_pVCR->Hook_GetKeyState
+#define VCRHook_recv g_pVCR->Hook_recv
+#define VCRHook_send g_pVCR->Hook_send
+#define VCRGenericRecord g_pVCR->GenericRecord
+#define VCRGenericPlayback g_pVCR->GenericPlayback
+#define VCRGenericValue g_pVCR->GenericValue
+#define VCRGetPercentCompleted g_pVCR->GetPercentCompleted
+#define VCRHook_CreateThread g_pVCR->Hook_CreateThread
+#define VCRHook_WaitForSingleObject g_pVCR->Hook_WaitForSingleObject
+#define VCRHook_EnterCriticalSection g_pVCR->Hook_EnterCriticalSection
+#define VCRHook_Time g_pVCR->Hook_Time
+#define VCRHook_WaitForMultipleObjects( a, b, c, d) g_pVCR->Hook_WaitForMultipleObjects( a, (const void **)b, c, d)
+#else
+#define VCRStart( a, b, c ) (1)
+#define VCREnd ((void)(0))
+#define VCRGetVCRTraceInterface (NULL)
+#define VCRGetMode() (VCR_Disabled)
+#define VCRSetEnabled( a ) ((void)(0))
+#define VCRSyncToken( a ) ((void)(0))
+#define VCRGenericRecord MUST_IFDEF_OUT_GenericRecord
+#define VCRGenericPlayback MUST_IFDEF_OUT_GenericPlayback
+#define VCRGenericValue MUST_IFDEF_OUT_GenericValue
+#define VCRGenericString MUST_IFDEF_OUT_GenericString
+#define VCRGenericValueVerify MUST_IFDEF_OUT_GenericValueVerify
+#define VCRGetPercentCompleted() (0.0f)
+#define VCRHook_Sys_FloatTime Sys_FloatTime
+#define VCRHook_PeekMessage PeekMessage
+#define VCRHook_RecordGameMsg RecordGameMsg
+#define VCRHook_RecordEndGameMsg RecordEndGameMsg
+#define VCRHook_PlaybackGameMsg PlaybackGameMsg
+#define VCRHook_recvfrom recvfrom
+#define VCRHook_GetCursorPos GetCursorPos
+#define VCRHook_ScreenToClient ScreenToClient
+#define VCRHook_Cmd_Exec( a ) ((void)(0))
+#define VCRHook_GetCommandLine GetCommandLine
+#define VCRHook_RegOpenKeyEx RegOpenKeyEx
+#define VCRHook_RegSetValueEx RegSetValueEx
+#define VCRHook_RegQueryValueEx RegQueryValueEx
+#define VCRHook_RegCreateKeyEx RegCreateKeyEx
+#define VCRHook_RegCloseKey RegCloseKey
+#define VCRHook_GetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents
+#define VCRHook_ReadConsoleInput ReadConsoleInput
+#define VCRHook_LocalTime( a ) memset(a, 0, sizeof(*a));
+#define VCRHook_GetKeyState GetKeyState
+#define VCRHook_recv recv
+#define VCRHook_send send
+#if defined( _X360 )
+#define VCRHook_CreateThread CreateThread
+#else
+#define VCRHook_CreateThread (void*)_beginthreadex
+#endif
+#define VCRHook_WaitForSingleObject WaitForSingleObject
+#define VCRHook_EnterCriticalSection EnterCriticalSection
+#define VCRHook_WaitForMultipleObjects( a, b, c, d) WaitForMultipleObjects( a, (const HANDLE *)b, c, d)
+#define VCRHook_Time Time
+#endif
+
+#endif // VCRMODE_H
diff --git a/public/tier0/vprof.h b/public/tier0/vprof.h
new file mode 100644
index 0000000..1c7321b
--- /dev/null
+++ b/public/tier0/vprof.h
@@ -0,0 +1,1440 @@
+//========= Copyright 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_telemetry.h"
+
+// VProf is enabled by default in all configurations -except- X360 Retail.
+#if !( defined( _X360 ) && defined( _CERT ) )
+#define VPROF_ENABLED
+#endif
+
+#if defined(_X360) && defined(VPROF_ENABLED)
+#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
+
+// enable this to use pix (360 only)
+// #define VPROF_PIX 1
+
+#if 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_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")
+#define VPROF_BUDGETGROUP_SLEEPING _T("Sleeping")
+#define VPROF_BUDGETGROUP_THREADINGMAIN _T("ThreadingMain")
+#define VPROF_BUDGETGROUP_HTMLSURFACE _T("HTMLSurface")
+#define VPROF_BUDGETGROUP_VGUI VPROF_BUDGETGROUP_HTMLSURFACE
+#define VPROF_BUDGETGROUP_TENFOOT VPROF_BUDGETGROUP_HTMLSURFACE
+#define VPROF_BUDGETGROUP_STEAMUI VPROF_BUDGETGROUP_HTMLSURFACE
+#define VPROF_BUDGETGROUP_ATTRIBUTES _T("Attributes")
+#define VPROF_BUDGETGROUP_FINDATTRIBUTE _T("FindAttribute")
+#define VPROF_BUDGETGROUP_FINDATTRIBUTEUNSAFE _T("FindAttributeUnsafe")
+
+#ifdef _X360
+// update flags
+#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
+
+//these macros exist to create VProf_<line number> variables. This is important because it avoids /analyze warnings about variable aliasing when VPROF's are nested within each other, and allows
+//for multiple VPROF's to exist within the same scope. Three macros must be used to force the __LINE__ to be resolved prior to the token concatenation, but just ignore the _INTERNAL macros and use
+//the VPROF_VAR_NAME
+#define VPROF_VAR_NAME_INTERNAL_CAT(a, b) a##b
+#define VPROF_VAR_NAME_INTERNAL( a, b ) VPROF_VAR_NAME_INTERNAL_CAT( a, b )
+#define VPROF_VAR_NAME( a ) VPROF_VAR_NAME_INTERNAL( a, __LINE__ )
+
+#define VPROF_0(name,group,assertAccounted,budgetFlags) tmZone( TELEMETRY_LEVEL2, TMZF_NONE, "(%s)%s", group, name ); CVProfScope VPROF_VAR_NAME( VProf_ )(name, 0, group, assertAccounted, budgetFlags);
+
+#if VPROF_LEVEL > 0
+#define VPROF_1(name,group,assertAccounted,budgetFlags) tmZone( TELEMETRY_LEVEL3, TMZF_NONE, "(%s)%s", group, name ); CVProfScope VPROF_VAR_NAME( VProf_ )(name, 1, group, assertAccounted, budgetFlags);
+#else
+#define VPROF_1(name,group,assertAccounted,budgetFlags) ((void)0)
+#endif
+
+#if VPROF_LEVEL > 1
+#define VPROF_2(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 2, group, assertAccounted, budgetFlags);
+#else
+#define VPROF_2(name,group,assertAccounted,budgetFlags) ((void)0)
+#endif
+
+#if VPROF_LEVEL > 2
+#define VPROF_3(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 3, group, assertAccounted, budgetFlags);
+#else
+#define VPROF_3(name,group,assertAccounted,budgetFlags) ((void)0)
+#endif
+
+#if VPROF_LEVEL > 3
+#define VPROF_4(name,group,assertAccounted,budgetFlags) CVProfScope VPROF_VAR_NAME( VProf_ )(name, 4, group, assertAccounted, budgetFlags);
+#else
+#define VPROF_4(name,group,assertAccounted,budgetFlags) ((void)0)
+#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 )
+
+#else
+
+#define VPROF( name ) ((void)0)
+#define VPROF_ASSERT_ACCOUNTED( name ) ((void)0)
+#define VPROF_( name, detail, group, bAssertAccounted, 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()
+
+#define VPROF_INCREMENT_COUNTER(name,amount) ((void)0)
+#define VPROF_INCREMENT_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 DBG_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_TELEMETRY,
+};
+
+class DBG_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 _X360
+ 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 );
+
+ // 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();
+
+ typedef void ( __cdecl *StreamOut_t )( const char* pszFormat, ... );
+ // Set the output function used for all vprof reports. Call this with NULL
+ // to set it to the default output function.
+ void SetOutputStream( StreamOut_t outputStream );
+ 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 char *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; }
+
+#ifndef _X360
+ bool UsePME( void ) { return ( m_bPMEInit && m_bPMEEnabled ); }
+#else
+ bool UsePME( void ) { return ( CPMCData::IsInitialized() && 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 _X360
+ int m_UpdateMode;
+ CPUTraceState m_iCPUTraceEnabled;
+ 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
+
+ unsigned m_TargetThreadId;
+
+ StreamOut_t m_pOutputStream;
+};
+
+//-------------------------------------
+
+DBG_INTERFACE CVProfile g_VProfCurrentProfile;
+
+
+//-----------------------------------------------------------------------------
+
+DBG_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:
+ 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()
+{
+ Assert( m_pszName );
+ 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 _X360
+ VXProfileStart();
+ 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 )
+ : 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;
+ }
+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/public/tier0/vprof_telemetry.h b/public/tier0/vprof_telemetry.h
new file mode 100644
index 0000000..740f381
--- /dev/null
+++ b/public/tier0/vprof_telemetry.h
@@ -0,0 +1,154 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Real-Time Hierarchical Telemetry Profiling
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef VPROF_TELEMETRY_H
+#define VPROF_TELEMETRY_H
+
+#if !defined( MAKE_VPC )
+
+#if !defined( RAD_TELEMETRY_DISABLED ) && ( defined( IS_WINDOWS_PC ) || defined( _LINUX ) )
+// Rad Telemetry profiling is enabled on Win32 and Win64.
+#define RAD_TELEMETRY_ENABLED
+#endif
+
+#endif // !MAKE_VPC
+
+
+#if !defined( RAD_TELEMETRY_ENABLED )
+
+//
+// Kill all tmZone() macros, etc.
+//
+#include "tmapi_dummy.h"
+
+inline void TelemetryTick() {}
+inline void TelemetrySetLevel( unsigned int Level ) {}
+#define TelemetrySetLockName( _ctx, _location, _description )
+
+class CTelemetryLock
+{
+public:
+ CTelemetryLock(void *plocation, const char *description) {}
+ ~CTelemetryLock() {}
+ void Locked() {}
+ void Unlocked() {}
+};
+
+class CTelemetrySpikeDetector
+{
+public:
+ CTelemetrySpikeDetector( const char *msg, uint32 threshold = 50 ) {}
+ ~CTelemetrySpikeDetector() { }
+};
+
+#define TM_ZONE_DEFAULT( context )
+#define TM_ZONE_DEFAULT_PARAM( context, string_param )
+
+#else
+
+//
+// Telemetry is enabled. Include the telemetry header.
+//
+#include "../../thirdparty/telemetry/include/telemetry.h"
+// Different versions of radbase.h define RADCOPYRIGHT to different values. So undef that here.
+#undef RADCOPYRIGHT
+
+struct TelemetryData
+{
+ HTELEMETRY tmContext[32];
+ float flRDTSCToMilliSeconds; // Conversion from tmFastTime() (rdtsc) to milliseconds.
+ uint32 FrameCount; // Count of frames to capture before turning off.
+ char ServerAddress[128]; // Server name to connect to.
+ int playbacktick; // GetPlaybackTick() value from demo file (or 0 if not playing a demo).
+ uint32 DemoTickStart; // Start telemetry on demo tick #
+ uint32 DemoTickEnd; // End telemetry on demo tick #
+ uint32 Level; // Current Telemetry level (Use TelemetrySetLevel to modify)
+};
+PLATFORM_INTERFACE TelemetryData g_Telemetry;
+
+PLATFORM_INTERFACE void TelemetryTick();
+PLATFORM_INTERFACE void TelemetrySetLevel( unsigned int Level );
+
+#define TELEMETRY_LEVEL0 g_Telemetry.tmContext[0] // high level tmZone()
+#define TELEMETRY_LEVEL1 g_Telemetry.tmContext[1] // lower level tmZone(), tmZoneFiltered()
+#define TELEMETRY_LEVEL2 g_Telemetry.tmContext[2] // VPROF_0
+#define TELEMETRY_LEVEL3 g_Telemetry.tmContext[3] // VPROF_1
+#define TELEMETRY_LEVEL4 g_Telemetry.tmContext[4] // VPROF_2
+#define TELEMETRY_LEVEL5 g_Telemetry.tmContext[5] // VPROF_3
+#define TELEMETRY_LEVEL6 g_Telemetry.tmContext[6] // VPROF_4
+
+#define TM_ZONE_DEFAULT( context ) tmZone(context, TMZF_NONE, __FUNCTION__ )
+#define TM_ZONE_DEFAULT_PARAM( context, string_param ) tmZone(context, TMZF_NONE, "%s( %s )", __FUNCTION__ , tmDynamicString( context, (string_param) ) )
+
+#define TelemetrySetLockName( _ctx, _location, _description ) \
+ do \
+ { \
+ static bool s_bNameSet = false; \
+ if( _ctx && !s_bNameSet ) \
+ { \
+ tmLockName( _ctx, _location, _description ); \
+ s_bNameSet = true; \
+ } \
+ } while( 0 )
+
+class CTelemetryLock
+{
+public:
+ CTelemetryLock(void *plocation, const char *description)
+ {
+ m_plocation = (const char *)plocation;
+ m_description = description;
+ TelemetrySetLockName( TELEMETRY_LEVEL1, m_plocation, m_description );
+ tmTryLock( TELEMETRY_LEVEL1, m_plocation, "%s", m_description );
+ }
+ ~CTelemetryLock()
+ {
+ Unlocked();
+ }
+ void Locked()
+ {
+ tmEndTryLock( TELEMETRY_LEVEL1, m_plocation, TMLR_SUCCESS );
+ tmSetLockState( TELEMETRY_LEVEL1, m_plocation, TMLS_LOCKED, "%s Locked", m_description );
+ }
+ void Unlocked()
+ {
+ if( m_plocation )
+ {
+ tmSetLockState( TELEMETRY_LEVEL1, m_plocation, TMLS_RELEASED, "%s Released", m_description );
+ m_plocation = NULL;
+ }
+ }
+
+public:
+ const char *m_plocation;
+ const char *m_description;
+};
+
+class CTelemetrySpikeDetector
+{
+public:
+ // Spews Telemetry message when threshold hit (in milliseconds.)
+ CTelemetrySpikeDetector( const char *msg, float threshold = 5 ) :
+ m_message( msg ), m_threshold( threshold ), time0( tmFastTime() ) {}
+ ~CTelemetrySpikeDetector()
+ {
+ float time = ( tmFastTime() - time0 ) * g_Telemetry.flRDTSCToMilliSeconds;
+ if( time >= m_threshold )
+ {
+ tmMessage( TELEMETRY_LEVEL0, TMMF_ICON_NOTE | TMMF_SEVERITY_WARNING, "(source/spike)%s %.2fms %t", m_message, time, tmSendCallStack( TELEMETRY_LEVEL0, 0 ) );
+ }
+ }
+
+private:
+ TmU64 time0;
+ float m_threshold;
+ const char *m_message;
+};
+
+#endif // RAD_TELEMETRY_ENABLED
+
+#endif // VPROF_TELEMETRY_H
diff --git a/public/tier0/wchartypes.h b/public/tier0/wchartypes.h
new file mode 100644
index 0000000..814470f
--- /dev/null
+++ b/public/tier0/wchartypes.h
@@ -0,0 +1,109 @@
+//========= Copyright 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
+
+#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(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).
+typedef unsigned char uint8;
+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
+
+#ifdef _WIN32
+#include <tchar.h>
+#else
+#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
+#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
+
+#if defined( _MSC_VER ) || defined( WIN32 )
+typedef wchar_t uchar16;
+typedef unsigned int uchar32;
+#else
+typedef unsigned short uchar16;
+typedef wchar_t uchar32;
+#endif
+
+#ifdef FORCED_UNICODE
+#undef _UNICODE
+#endif
+
+// Turn valve defines back on
+#include "tier0/valve_on.h"
+
+
+#endif // WCHARTYPES
+
+
diff --git a/public/tier0/xbox_codeline_defines.h b/public/tier0/xbox_codeline_defines.h
new file mode 100644
index 0000000..2e3b2c5
--- /dev/null
+++ b/public/tier0/xbox_codeline_defines.h
@@ -0,0 +1,16 @@
+//========= Copyright 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