1
0
forked from 0ad/0ad

# code cleanup/fixes

improvements from work:
- no longer export classes; instead inline functions where it makes
sense (e.g. the scope timers) or export the member functions directly
- fix icc11 warnings
- add some comments

This was SVN commit r6531.
This commit is contained in:
janwas 2008-12-16 21:13:04 +00:00
parent 96eb854667
commit 387722d41e
13 changed files with 208 additions and 196 deletions

View File

@ -27,7 +27,7 @@
* *
* opaque! do not read/write any fields! * opaque! do not read/write any fields!
**/ **/
struct LIB_API Bucket struct Bucket
{ {
/** /**
* currently open bucket. * currently open bucket.

View File

@ -1,6 +1,8 @@
#ifndef INCLUDED_SHARED_PTR #ifndef INCLUDED_SHARED_PTR
#define INCLUDED_SHARED_PTR #define INCLUDED_SHARED_PTR
#include "lib/sysdep/arch/x86_x64/x86_x64.h"
struct DummyDeleter struct DummyDeleter
{ {
template<class T> template<class T>
@ -27,4 +29,19 @@ struct ArrayDeleter
// (note: uses CheckedArrayDeleter) // (note: uses CheckedArrayDeleter)
LIB_API shared_ptr<u8> Allocate(size_t size); LIB_API shared_ptr<u8> Allocate(size_t size);
struct AlignedDeleter
{
template<class T>
void operator()(T* t)
{
_mm_free(t);
}
};
template<class T>
shared_ptr<T> AllocateAligned(size_t size)
{
return shared_ptr<T>((T*)_mm_malloc(size, x86_x64_L1CacheLineSize()), AlignedDeleter());
}
#endif // #ifndef INCLUDED_SHARED_PTR #endif // #ifndef INCLUDED_SHARED_PTR

View File

@ -157,7 +157,7 @@ namespace detail
namespace noncopyable_ // protection from unintended ADL namespace noncopyable_ // protection from unintended ADL
{ {
class LIB_API noncopyable class noncopyable
{ {
protected: protected:
noncopyable() {} noncopyable() {}

View File

@ -450,6 +450,9 @@ LIB_API void debug_puts(const char* text);
/** /**
* return the caller of a certain function on the call stack. * return the caller of a certain function on the call stack.
* *
* this function is useful for recording (partial) stack traces for
* memory allocation tracking, etc.
*
* @param context, lastFuncToSkip - see debug_DumpStack * @param context, lastFuncToSkip - see debug_DumpStack
* @return address of the caller * @return address of the caller
**/ **/

View File

@ -23,13 +23,13 @@
struct PathTraits; struct PathTraits;
typedef fs::basic_path<std::string, PathTraits> Path; typedef fs::basic_path<std::string, PathTraits> Path;
struct LIB_API PathTraits struct PathTraits
{ {
typedef std::string internal_string_type; typedef std::string internal_string_type;
typedef std::string external_string_type; typedef std::string external_string_type;
static external_string_type to_external(const Path&, const internal_string_type& src); static LIB_API external_string_type to_external(const Path&, const internal_string_type& src);
static internal_string_type to_internal(const external_string_type& src); static LIB_API internal_string_type to_internal(const external_string_type& src);
}; };
namespace boost namespace boost

View File

@ -17,13 +17,10 @@
#include "vfs_populate.h" #include "vfs_populate.h"
#include "lib/timer.h" #include "lib/timer.h"
TIMER_ADD_CLIENT(tc_lookup);
LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDirectory*& directory, VfsFile** pfile, size_t flags) LibError vfs_Lookup(const VfsPath& pathname, VfsDirectory* startDirectory, VfsDirectory*& directory, VfsFile** pfile, size_t flags)
{ {
TIMER_ACCRUE(tc_lookup);
// extract and validate flags (ensure no unknown bits are set) // extract and validate flags (ensure no unknown bits are set)
const bool addMissingDirectories = (flags & VFS_LOOKUP_ADD) != 0; const bool addMissingDirectories = (flags & VFS_LOOKUP_ADD) != 0;
const bool createMissingDirectories = (flags & VFS_LOOKUP_CREATE) != 0; const bool createMissingDirectories = (flags & VFS_LOOKUP_CREATE) != 0;

View File

@ -13,11 +13,17 @@
#include "lib/file/vfs/vfs_path.h" #include "lib/file/vfs/vfs_path.h"
// 0 = invalid handle value; < 0 is an error code. /**
// 64 bits, because we want tags to remain unique: tag overflow may * `handle' representing a reference to a resource (sound, texture, etc.)
// let handle use errors slip through, or worse, cause spurious errors. *
// with 32 bits, we'd need >= 12 for the index, leaving < 512K tags - * 0 is the (silently ignored) invalid handle value; < 0 is an error code.
// not a lot. *
* this is 64 bits because we want tags to remain unique. (tags are a
* counter that disambiguate several subsequent uses of the same
* resource array slot). 32-bit handles aren't enough because the index
* field requires at least 12 bits, thus leaving only about 512K possible
* tag values.
**/
typedef i64 Handle; typedef i64 Handle;
#endif // #ifndef INCLUDED_HANDLE #endif // #ifndef INCLUDED_HANDLE

View File

@ -98,9 +98,9 @@ template<typename T>
class numa_Allocator class numa_Allocator
{ {
public: public:
shared_ptr<T> operator()(size_t size) const shared_ptr<T> operator()(size_t size, LargePageDisposition largePageDisposition = LPD_DEFAULT, size_t* ppageSize = 0) const
{ {
return shared_ptr<T>((T*)numa_Allocate(size), numa_Deleter<T>()); return shared_ptr<T>((T*)numa_Allocate(size, largePageDisposition, ppageSize), numa_Deleter<T>());
} }
}; };

View File

@ -24,10 +24,10 @@ int debug_IsPointerBogus(const void* p)
if(p < (void*)0x10000) if(p < (void*)0x10000)
return true; return true;
#if ARCH_AMD64 #if ARCH_AMD64
if(p == (const void*)0xCCCCCCCCCCCCCCCCull) if(p == (const void*)(uintptr_t)0xCCCCCCCCCCCCCCCCull)
return true; return true;
#elif ARCH_IA32 #elif ARCH_IA32
if(p == (const void*)0xCCCCCCCCul) if(p == (const void*)(uintptr_t)0xCCCCCCCCul)
return true; return true;
#endif #endif

View File

@ -120,7 +120,7 @@ struct TI_FINDCHILDREN_PARAMS2
// actual implementation; made available so that functions already under // actual implementation; made available so that functions already under
// the lock don't have to unlock (slow) to avoid recursive locking. // the lock don't have to unlock (slow) to avoid recursive locking.
static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, char* file, int* line) static LibError ResolveSymbol_lk(void* ptr_of_interest, char* sym_name, char* file, int* line)
{ {
sym_init(); sym_init();
@ -183,7 +183,7 @@ static LibError debug_resolve_symbol_lk(void* ptr_of_interest, char* sym_name, c
LibError debug_ResolveSymbol(void* ptr_of_interest, char* sym_name, char* file, int* line) LibError debug_ResolveSymbol(void* ptr_of_interest, char* sym_name, char* file, int* line)
{ {
WinScopedLock lock(WDBG_SYM_CS); WinScopedLock lock(WDBG_SYM_CS);
return debug_resolve_symbol_lk(ptr_of_interest, sym_name, file, line); return ResolveSymbol_lk(ptr_of_interest, sym_name, file, line);
} }
@ -281,10 +281,15 @@ static LibError ia32_walk_stack(_tagSTACKFRAME64* sf)
#endif #endif
// note: RtlCaptureStackBackTrace (http://msinilo.pl/blog/?p=40)
// is likely to be much faster than StackWalk64 (especially relevant
// for debug_GetCaller), but wasn't known during development and
// remains undocumented.
typedef VOID (WINAPI *PRtlCaptureContext)(PCONTEXT); typedef VOID (WINAPI *PRtlCaptureContext)(PCONTEXT);
static PRtlCaptureContext s_RtlCaptureContext; static PRtlCaptureContext s_RtlCaptureContext;
LibError wdbg_sym_WalkStack(StackFrameCallback cb, uintptr_t cbData, const CONTEXT* pcontext, const char* lastFuncToSkip) LibError wdbg_sym_WalkStack(StackFrameCallback cb, uintptr_t cbData, const CONTEXT* pcontext, const char* lastFuncToSkip)
{ {
// to function properly, StackWalk64 requires a CONTEXT on // to function properly, StackWalk64 requires a CONTEXT on
@ -1207,7 +1212,7 @@ static LibError dump_sym_function_type(DWORD UNUSED(type_id), const u8* p, DumpS
// isn't exposed via TI_GET_SYMNAME, so we resolve it ourselves. // isn't exposed via TI_GET_SYMNAME, so we resolve it ourselves.
char name[DBG_SYMBOL_LEN]; char name[DBG_SYMBOL_LEN];
LibError err = debug_resolve_symbol_lk((void*)p, name, 0, 0); LibError err = ResolveSymbol_lk((void*)p, name, 0, 0);
if(state.indirection == 0) if(state.indirection == 0)
out(L"0x%p ", p); out(L"0x%p ", p);
@ -1767,7 +1772,7 @@ static LibError dump_frame_cb(const _tagSTACKFRAME64* sf, uintptr_t UNUSED(cbDat
void* func = (void*)(uintptr_t)sf->AddrPC.Offset; void* func = (void*)(uintptr_t)sf->AddrPC.Offset;
char func_name[DBG_SYMBOL_LEN]; char file[DBG_FILE_LEN]; int line; char func_name[DBG_SYMBOL_LEN]; char file[DBG_FILE_LEN]; int line;
LibError ret = debug_resolve_symbol_lk(func, func_name, file, &line); LibError ret = ResolveSymbol_lk(func, func_name, file, &line);
if(ret == INFO::OK) if(ret == INFO::OK)
{ {
// don't trace back further than the app's entry point // don't trace back further than the app's entry point

View File

@ -263,7 +263,7 @@ match_string (const char **buf, const char **strs)
int i = 0; int i = 0;
for (i = 0; strs[i] != NULL; ++i) { for (i = 0; strs[i] != NULL; ++i) {
int len = strlen (strs[i]); size_t len = strlen (strs[i]);
if (strncasecmp (*buf, strs[i], len) == 0) { if (strncasecmp (*buf, strs[i], len) == 0) {
*buf += len; *buf += len;

View File

@ -17,17 +17,12 @@
#include <stdarg.h> #include <stdarg.h>
#include "lib/posix/posix_time.h" #include "lib/posix/posix_time.h"
#include "lib/sysdep/os_cpu.h"
#if OS_WIN #if OS_WIN
#include "lib/sysdep/os/win/whrt/whrt.h" #include "lib/sysdep/os/win/whrt/whrt.h"
#endif #endif
#if OS_UNIX #if OS_UNIX
# include <unistd.h> # include <unistd.h>
#endif #endif
#include "lib/config2.h" // CONFIG2_TIMER_ALLOW_RDTSC
#if ARCH_X86_X64 && CONFIG2_TIMER_ALLOW_RDTSC
# include "lib/sysdep/arch/x86_x64/x86_x64.h" // x86_x64_rdtsc
#endif
#if OS_UNIX || OS_WIN #if OS_UNIX || OS_WIN
# define HAVE_GETTIMEOFDAY 1 # define HAVE_GETTIMEOFDAY 1
@ -124,147 +119,6 @@ double timer_Resolution()
} }
//-----------------------------------------------------------------------------
ScopeTimer::ScopeTimer(const char* description)
: m_t0(timer_Time()), m_description(description)
{
}
ScopeTimer::~ScopeTimer()
{
double t1 = timer_Time();
double dt = t1-m_t0;
// determine scale factor for pretty display
double scale = 1e6;
const char* unit = "us";
if(dt > 1.0)
scale = 1, unit = "s";
else if(dt > 1e-3)
scale = 1e3, unit = "ms";
debug_printf("TIMER| %s: %g %s\n", m_description, dt*scale, unit);
}
//-----------------------------------------------------------------------------
// TimerUnit
// since TIMER_ACCRUE et al. are called so often, we try to keep
// overhead to an absolute minimum. storing raw tick counts (e.g. CPU cycles
// returned by ia32_rdtsc) instead of absolute time has two benefits:
// - no need to convert from raw->time on every call
// (instead, it's only done once when displaying the totals)
// - possibly less overhead to querying the time itself
// (timer_Time may be using slower time sources with ~3us overhead)
//
// however, the cycle count is not necessarily a measure of wall-clock time
// (see http://www.gamedev.net/reference/programming/features/timing).
// therefore, on systems with SpeedStep active, measurements of I/O or other
// non-CPU bound activity may be skewed. this is ok because the timer is
// only used for profiling; just be aware of the issue.
// if this is a problem, disable CONFIG2_TIMER_ALLOW_RDTSC.
//
// note that overflow isn't an issue either way (63 bit cycle counts
// at 10 GHz cover intervals of 29 years).
#if ARCH_X86_X64 && CONFIG2_TIMER_ALLOW_RDTSC
void TimerUnit::SetToZero()
{
m_ticks = 0;
}
void TimerUnit::SetFromTimer()
{
m_ticks = x86_x64_rdtsc();
}
void TimerUnit::AddDifference(TimerUnit t0, TimerUnit t1)
{
m_ticks += t1.m_ticks - t0.m_ticks;
}
void TimerUnit::Subtract(TimerUnit t)
{
m_ticks -= t.m_ticks;
}
std::string TimerUnit::ToString() const
{
debug_assert(m_ticks >= 0.0);
// determine scale factor for pretty display
double scale = 1.0;
const char* unit = " c";
if(m_ticks > 10000000000LL) // 10 Gc
scale = 1e-9, unit = " Gc";
else if(m_ticks > 10000000) // 10 Mc
scale = 1e-6, unit = " Mc";
else if(m_ticks > 10000) // 10 kc
scale = 1e-3, unit = " kc";
std::stringstream ss;
ss << m_ticks*scale;
ss << unit;
return ss.str();
}
double TimerUnit::ToSeconds() const
{
return m_ticks / os_cpu_ClockFrequency();
}
#else
void TimerUnit::SetToZero()
{
m_seconds = 0.0;
}
void TimerUnit::SetFromTimer()
{
m_seconds = timer_Time();
}
void TimerUnit::AddDifference(TimerUnit t0, TimerUnit t1)
{
m_seconds += t1.m_seconds - t0.m_seconds;
}
void TimerUnit::Subtract(TimerUnit t)
{
m_seconds -= t.m_seconds;
}
std::string TimerUnit::ToString() const
{
debug_assert(m_seconds >= 0.0);
// determine scale factor for pretty display
double scale = 1e6;
const char* unit = " us";
if(m_seconds > 1.0)
scale = 1, unit = " s";
else if(m_seconds > 1e-3)
scale = 1e3, unit = " ms";
std::stringstream ss;
ss << m_seconds*scale;
ss << unit;
return ss.str();
}
double TimerUnit::ToSeconds() const
{
return m_seconds;
}
#endif
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// client API // client API
@ -319,18 +173,3 @@ void timer_DisplayClientTotals()
debug_printf("-----------------------------------------------------\n"); debug_printf("-----------------------------------------------------\n");
} }
ScopeTimerAccrue::ScopeTimerAccrue(TimerClient* tc)
: m_tc(tc)
{
m_t0.SetFromTimer();
}
ScopeTimerAccrue::~ScopeTimerAccrue()
{
TimerUnit t1;
t1.SetFromTimer();
timer_BillClient(m_tc, m_t0, t1);
}

View File

@ -11,6 +11,12 @@
#ifndef INCLUDED_TIMER #ifndef INCLUDED_TIMER
#define INCLUDED_TIMER #define INCLUDED_TIMER
#include "lib/config2.h" // CONFIG2_TIMER_ALLOW_RDTSC
#if ARCH_X86_X64 && CONFIG2_TIMER_ALLOW_RDTSC
# include "lib/sysdep/arch/x86_x64/x86_x64.h" // x86_x64_rdtsc
# include "lib/sysdep/os_cpu.h" // os_cpu_ClockFrequency
#endif
/** /**
* timer_Time will subsequently return values relative to the current time. * timer_Time will subsequently return values relative to the current time.
**/ **/
@ -31,11 +37,29 @@ LIB_API double timer_Resolution(void);
// scope timing // scope timing
/// used by TIMER /// used by TIMER
class LIB_API ScopeTimer : noncopyable class ScopeTimer : noncopyable
{ {
public: public:
ScopeTimer(const char* description); ScopeTimer(const char* description)
~ScopeTimer(); : m_t0(timer_Time()), m_description(description)
{
}
~ScopeTimer()
{
double t1 = timer_Time();
double dt = t1-m_t0;
// determine scale factor for pretty display
double scale = 1e6;
const char* unit = "us";
if(dt > 1.0)
scale = 1, unit = "s";
else if(dt > 1e-3)
scale = 1e3, unit = "ms";
debug_printf("TIMER| %s: %g %s\n", m_description, dt*scale, unit);
}
private: private:
double m_t0; double m_t0;
@ -91,21 +115,132 @@ private:
// this supplements in-game profiling by providing low-overhead, // this supplements in-game profiling by providing low-overhead,
// high resolution time accounting of specific areas. // high resolution time accounting of specific areas.
union LIB_API TimerUnit // since TIMER_ACCRUE et al. are called so often, we try to keep
// overhead to an absolute minimum. storing raw tick counts (e.g. CPU cycles
// returned by ia32_rdtsc) instead of absolute time has two benefits:
// - no need to convert from raw->time on every call
// (instead, it's only done once when displaying the totals)
// - possibly less overhead to querying the time itself
// (timer_Time may be using slower time sources with ~3us overhead)
//
// however, the cycle count is not necessarily a measure of wall-clock time
// (see http://www.gamedev.net/reference/programming/features/timing).
// therefore, on systems with SpeedStep active, measurements of I/O or other
// non-CPU bound activity may be skewed. this is ok because the timer is
// only used for profiling; just be aware of the issue.
// if this is a problem, disable CONFIG2_TIMER_ALLOW_RDTSC.
//
// note that overflow isn't an issue either way (63 bit cycle counts
// at 10 GHz cover intervals of 29 years).
#if ARCH_X86_X64 && CONFIG2_TIMER_ALLOW_RDTSC
class TimerUnit
{ {
public: public:
void SetToZero(); void SetToZero()
void SetFromTimer(); {
void AddDifference(TimerUnit t0, TimerUnit t1); m_ticks = 0;
void Subtract(TimerUnit t); }
std::string ToString() const;
double ToSeconds() const; void SetFromTimer()
{
m_ticks = x86_x64_rdtsc();
}
void AddDifference(TimerUnit t0, TimerUnit t1)
{
m_ticks += t1.m_ticks - t0.m_ticks;
}
void Subtract(TimerUnit t)
{
m_ticks -= t.m_ticks;
}
std::string ToString() const
{
debug_assert(m_ticks >= 0.0);
// determine scale factor for pretty display
double scale = 1.0;
const char* unit = " c";
if(m_ticks > 10000000000LL) // 10 Gc
scale = 1e-9, unit = " Gc";
else if(m_ticks > 10000000) // 10 Mc
scale = 1e-6, unit = " Mc";
else if(m_ticks > 10000) // 10 kc
scale = 1e-3, unit = " kc";
std::stringstream ss;
ss << m_ticks*scale;
ss << unit;
return ss.str();
}
double ToSeconds() const
{
return m_ticks / os_cpu_ClockFrequency();
}
private: private:
u64 m_ticks; u64 m_ticks;
};
#else
class TimerUnit
{
public:
void SetToZero()
{
m_seconds = 0.0;
}
void SetFromTimer()
{
m_seconds = timer_Time();
}
void AddDifference(TimerUnit t0, TimerUnit t1)
{
m_seconds += t1.m_seconds - t0.m_seconds;
}
void Subtract(TimerUnit t)
{
m_seconds -= t.m_seconds;
}
std::string ToString() const
{
debug_assert(m_seconds >= 0.0);
// determine scale factor for pretty display
double scale = 1e6;
const char* unit = " us";
if(m_seconds > 1.0)
scale = 1, unit = " s";
else if(m_seconds > 1e-3)
scale = 1e3, unit = " ms";
std::stringstream ss;
ss << m_seconds*scale;
ss << unit;
return ss.str(); }
double ToSeconds() const
{
return m_seconds;
}
private:
double m_seconds; double m_seconds;
}; };
#endif
// opaque - do not access its fields! // opaque - do not access its fields!
// note: must be defined here because clients instantiate them; // note: must be defined here because clients instantiate them;
// fields cannot be made private due to POD requirement. // fields cannot be made private due to POD requirement.
@ -159,11 +294,21 @@ LIB_API void timer_BillClient(TimerClient* tc, TimerUnit t0, TimerUnit t1);
LIB_API void timer_DisplayClientTotals(); LIB_API void timer_DisplayClientTotals();
/// used by TIMER_ACCRUE /// used by TIMER_ACCRUE
class LIB_API ScopeTimerAccrue class ScopeTimerAccrue
{ {
public: public:
ScopeTimerAccrue(TimerClient* tc); ScopeTimerAccrue(TimerClient* tc)
~ScopeTimerAccrue(); : m_tc(tc)
{
m_t0.SetFromTimer();
}
~ScopeTimerAccrue()
{
TimerUnit t1;
t1.SetFromTimer();
timer_BillClient(m_tc, m_t0, t1);
}
private: private:
TimerUnit m_t0; TimerUnit m_t0;