mirror of
https://github.com/nillerusr/source-engine.git
synced 2026-08-15 13:16:58 +00:00
1
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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 */
|
||||
@@ -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 */
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,153 @@
|
||||
//========= Copyright � 1996-2008, Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose: Tools for grabbing/dumping the stack at runtime
|
||||
//
|
||||
// $NoKeywords: $
|
||||
//=============================================================================//
|
||||
|
||||
#ifndef TIER0_STACKTOOLS_H
|
||||
#define TIER0_STACKTOOLS_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include "tier0/platform.h"
|
||||
|
||||
#if (defined( PLATFORM_WINDOWS ) || defined( PLATFORM_X360 )) && !defined( STEAM ) && !defined( _CERT ) && defined( TCHAR_IS_CHAR ) //designed for windows/x360, not built/tested with wide characters, not intended for release builds (but probably wouldn't damage anything)
|
||||
# define ENABLE_RUNTIME_STACK_TRANSLATION //uncomment to enable runtime stack translation tools. All of which use on-demand loading of necessary dll's and pdb's
|
||||
#endif
|
||||
|
||||
#if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
|
||||
//#define ENABLE_THREAD_PARENT_STACK_TRACING 1 //uncomment to actually enable tracking stack traces from threads and jobs to their parent thread. Must also define THREAD_PARENT_STACK_TRACE_SUPPORTED in threadtools.h
|
||||
# if defined( ENABLE_THREAD_PARENT_STACK_TRACING )
|
||||
# define THREAD_PARENT_STACK_TRACE_LENGTH 32
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
PLATFORM_INTERFACE int GetCallStack( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
|
||||
|
||||
//ONLY WORKS IF THE CRAWLED PORTION OF THE STACK DISABLES FRAME POINTER OMISSION (/Oy-) "vpc /nofpo"
|
||||
PLATFORM_INTERFACE int GetCallStack_Fast( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
|
||||
|
||||
typedef int (*FN_GetCallStack)( void **pReturnAddressesOut, int iArrayCount, int iSkipCount );
|
||||
|
||||
//where we'll find our PDB's for win32.
|
||||
PLATFORM_INTERFACE void SetStackTranslationSymbolSearchPath( const char *szSemicolonSeparatedList = NULL );
|
||||
PLATFORM_INTERFACE void StackToolsNotify_LoadedLibrary( const char *szLibName );
|
||||
|
||||
//maximum output sample "tier0.dll!TranslateStackInfo - u:\Dev\L4D\src\tier0\stacktools.cpp(162) + 4 bytes"
|
||||
enum TranslateStackInfo_StyleFlags_t
|
||||
{
|
||||
TSISTYLEFLAG_NONE = 0,
|
||||
TSISTYLEFLAG_MODULENAME = (1<<0), //start with module Sample: "tier0.dll!"
|
||||
TSISTYLEFLAG_SYMBOLNAME = (1<<1), //include the symbol name Sample: "TranslateStackInfo"
|
||||
TSISTYLEFLAG_FULLPATH = (1<<2), //include full path Sample: "u:\Dev\L4D\src\tier0\stacktools.cpp"
|
||||
TSISTYLEFLAG_SHORTPATH = (1<<3), //only include 2 directories Sample: "\src\tier0\stacktools.cpp"
|
||||
TSISTYLEFLAG_LINE = (1<<4), //file line number Sample: "(162)"
|
||||
TSISTYLEFLAG_LINEANDOFFSET = (1<<5), //file line + offset Sample: "(162) + 4 bytes"
|
||||
TSISTYLEFLAG_LAST = TSISTYLEFLAG_LINEANDOFFSET,
|
||||
TSISTYLEFLAG_DEFAULT = (TSISTYLEFLAG_MODULENAME | TSISTYLEFLAG_SYMBOLNAME | TSISTYLEFLAG_FULLPATH | TSISTYLEFLAG_LINEANDOFFSET), //produces sample above
|
||||
};
|
||||
|
||||
//Generates a formatted list of function information, returns number of translated entries
|
||||
//On 360 this generates a string that can be decoded by VXConsole in print functions. Optimal path for translation because it's one way. Other paths require multiple transactions.
|
||||
PLATFORM_INTERFACE int TranslateStackInfo( const void * const *pCallStack, int iCallStackCount, tchar *szOutput, int iOutBufferSize, const tchar *szEntrySeparator, TranslateStackInfo_StyleFlags_t style = TSISTYLEFLAG_DEFAULT );
|
||||
|
||||
PLATFORM_INTERFACE void PreloadStackInformation( void * const *pAddresses, int iAddressCount ); //caches data and reduces communication with VXConsole to speed up 360 decoding when using any of the Get***FromAddress() functions. Nop on PC.
|
||||
PLATFORM_INTERFACE bool GetFileAndLineFromAddress( const void *pAddress, tchar *pFileNameOut, int iMaxFileNameLength, uint32 &iLineNumberOut, uint32 *pDisplacementOut = NULL );
|
||||
PLATFORM_INTERFACE bool GetSymbolNameFromAddress( const void *pAddress, tchar *pSymbolNameOut, int iMaxSymbolNameLength, uint64 *pDisplacementOut = NULL );
|
||||
PLATFORM_INTERFACE bool GetModuleNameFromAddress( const void *pAddress, tchar *pModuleNameOut, int iMaxModuleNameLength );
|
||||
|
||||
|
||||
|
||||
class PLATFORM_CLASS CCallStackStorage //a helper class to grab a stack trace as close to the leaf code surface as possible, then pass it on to deeper functions intact with less unpredictable inlining pollution
|
||||
{
|
||||
public:
|
||||
CCallStackStorage( FN_GetCallStack GetStackFunction = GetCallStack, uint32 iSkipCalls = 0 );
|
||||
CCallStackStorage( const CCallStackStorage ©From )
|
||||
{
|
||||
iValidEntries = copyFrom.iValidEntries;
|
||||
memcpy( pStack, copyFrom.pStack, sizeof( void * ) * copyFrom.iValidEntries );
|
||||
}
|
||||
|
||||
void *pStack[128]; //probably too big, possibly too small for some applications. Don't want to spend the time figuring out how to generalize this without templatizing pollution or mallocs
|
||||
uint32 iValidEntries;
|
||||
};
|
||||
|
||||
|
||||
//Hold onto one of these to denote the top of a functional stack trace. Also allows us to string together threads to their parents
|
||||
class PLATFORM_CLASS CStackTop_Base
|
||||
{
|
||||
protected:
|
||||
#if defined( ENABLE_RUNTIME_STACK_TRANSLATION )
|
||||
CStackTop_Base *m_pPrevTop;
|
||||
void *m_pStackBase;
|
||||
void *m_pReplaceAddress;
|
||||
|
||||
void * const *m_pParentStackTrace;
|
||||
int m_iParentStackTraceLength;
|
||||
#endif
|
||||
};
|
||||
|
||||
//makes a copy of the parent stack
|
||||
class PLATFORM_CLASS CStackTop_CopyParentStack : public CStackTop_Base
|
||||
{
|
||||
public:
|
||||
CStackTop_CopyParentStack( void * const * pParentStackTrace, int iParentStackTraceLength );
|
||||
~CStackTop_CopyParentStack( void );
|
||||
};
|
||||
|
||||
//just references the parent stack. Assuming that you'll keep that memory around as long as you're keeping this Stack Top marker.
|
||||
class PLATFORM_CLASS CStackTop_ReferenceParentStack : public CStackTop_Base
|
||||
{
|
||||
public:
|
||||
CStackTop_ReferenceParentStack( void * const * pParentStackTrace = NULL, int iParentStackTraceLength = 0 );
|
||||
~CStackTop_ReferenceParentStack( void );
|
||||
void ReleaseParentStackReferences( void ); //in case you need to delete the parent stack trace before this class goes out of scope
|
||||
};
|
||||
|
||||
|
||||
//Encodes data so that every byte's most significant bit is a 1. Ensuring no null terminators.
|
||||
//This puts the encoded data in the 128-255 value range. Leaving all standard ascii characters for control.
|
||||
//Returns string length (not including the written null terminator as is standard).
|
||||
//Or if the buffer is too small. Returns negative of necessary buffer size (including room needed for null terminator)
|
||||
PLATFORM_INTERFACE int EncodeBinaryToString( const void *pToEncode, int iDataLength, char *pEncodeOut, int iEncodeBufferSize );
|
||||
|
||||
//Decodes a string produced by EncodeBinaryToString(). Safe to decode in place if you don't mind trashing your string, binary byte count always less than string byte count.
|
||||
//Returns:
|
||||
// >= 0 is the decoded data size
|
||||
// INT_MIN (most negative value possible) indicates an improperly formatted string (not our data)
|
||||
// all other negative values are the negative of how much dest buffer size is necessary.
|
||||
PLATFORM_INTERFACE int DecodeBinaryFromString( const char *pString, void *pDestBuffer, int iDestBufferSize, char **ppParseFinishOut = NULL );
|
||||
|
||||
|
||||
|
||||
|
||||
// 360<->VXConsole specific communication definitions
|
||||
#define XBX_CALLSTACKDECODEPREFIX ":CSDECODE["
|
||||
|
||||
enum StackTranslation_BinaryHandler_Command_t
|
||||
{
|
||||
ST_BHC_LOADEDLIBARY,
|
||||
ST_BHC_GETTRANSLATIONINFO,
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct FullStackInfo_t
|
||||
{
|
||||
const void *pAddress;
|
||||
char szModuleName[24];
|
||||
char szFileName[MAX_PATH/2];
|
||||
char szSymbol[64];
|
||||
uint32 iLine;
|
||||
uint32 iSymbolOffset;
|
||||
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
#endif //#ifndef TIER0_STACKTOOLS_H
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,7 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user