You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
7.8 KiB
426 lines
7.8 KiB
//========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#include "pch_tier0.h" |
|
#include "tier0/platform.h" |
|
#include "tier0/memalloc.h" |
|
#include "tier0/dbg.h" |
|
#include "tier0/threadtools.h" |
|
|
|
#include <sys/time.h> |
|
#include <unistd.h> |
|
|
|
#ifdef OSX |
|
#include <sys/sysctl.h> |
|
#include <mach/mach.h> |
|
#include <mach/mach_time.h> |
|
#endif |
|
|
|
|
|
static bool g_bBenchmarkMode = false; |
|
static double g_FakeBenchmarkTime = 0; |
|
static double g_FakeBenchmarkTimeInc = 1.0 / 66.0; |
|
|
|
|
|
bool Plat_IsInBenchmarkMode() |
|
{ |
|
return g_bBenchmarkMode; |
|
} |
|
|
|
void Plat_SetBenchmarkMode( bool bBenchmark ) |
|
{ |
|
g_bBenchmarkMode = bBenchmark; |
|
} |
|
|
|
|
|
|
|
#ifdef OSX |
|
|
|
static uint64 start_time = 0; |
|
static mach_timebase_info_data_t sTimebaseInfo; |
|
static double conversion = 0.0; |
|
|
|
void InitTime() |
|
{ |
|
start_time = mach_absolute_time(); |
|
mach_timebase_info(&sTimebaseInfo); |
|
conversion = 1e-9 * (double) sTimebaseInfo.numer / (double) sTimebaseInfo.denom; |
|
} |
|
|
|
uint64 Plat_GetClockStart() |
|
{ |
|
if ( !start_time ) |
|
{ |
|
InitTime(); |
|
} |
|
|
|
return start_time * conversion; |
|
} |
|
|
|
double Plat_FloatTime() |
|
{ |
|
if ( g_bBenchmarkMode ) |
|
{ |
|
g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; |
|
return g_FakeBenchmarkTime; |
|
} |
|
|
|
if ( !start_time ) |
|
{ |
|
InitTime(); |
|
} |
|
|
|
uint64 now = mach_absolute_time(); |
|
|
|
return ( now - start_time ) * conversion; |
|
} |
|
#else |
|
|
|
static int secbase = 0; |
|
|
|
void InitTime( struct timeval &tp ) |
|
{ |
|
secbase = tp.tv_sec; |
|
} |
|
|
|
uint64 Plat_GetClockStart() |
|
{ |
|
if ( !secbase ) |
|
{ |
|
struct timeval tp; |
|
gettimeofday( &tp, NULL ); |
|
InitTime( tp ); |
|
} |
|
|
|
return secbase; |
|
} |
|
|
|
|
|
double Plat_FloatTime() |
|
{ |
|
if ( g_bBenchmarkMode ) |
|
{ |
|
g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; |
|
return g_FakeBenchmarkTime; |
|
} |
|
|
|
struct timeval tp; |
|
|
|
gettimeofday( &tp, NULL ); |
|
|
|
if ( !secbase ) |
|
{ |
|
InitTime( tp ); |
|
return ( tp.tv_usec / 1000000.0 ); |
|
} |
|
|
|
return (( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0 ); |
|
} |
|
#endif |
|
|
|
|
|
uint32 Plat_MSTime() |
|
{ |
|
if ( g_bBenchmarkMode ) |
|
{ |
|
g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc; |
|
return (unsigned long)(g_FakeBenchmarkTime * 1000.0); |
|
} |
|
|
|
struct timeval tp; |
|
static int secbase = 0; |
|
|
|
gettimeofday( &tp, NULL ); |
|
|
|
if ( !secbase ) |
|
{ |
|
secbase = tp.tv_sec; |
|
return ( tp.tv_usec / 1000.0 ); |
|
} |
|
|
|
return (unsigned long)(( tp.tv_sec - secbase )*1000.0 + tp.tv_usec / 1000.0 ); |
|
|
|
} |
|
|
|
// Wraps the thread-safe versions of asctime. buf must be at least 26 bytes |
|
char *Plat_asctime( const struct tm *tm, char *buf, size_t bufsize ) |
|
{ |
|
return asctime_r( tm, buf ); |
|
} |
|
|
|
// Wraps the thread-safe versions of ctime. buf must be at least 26 bytes |
|
char *Plat_ctime( const time_t *timep, char *buf, size_t bufsize ) |
|
{ |
|
return ctime_r( timep, buf ); |
|
} |
|
|
|
// Wraps the thread-safe versions of gmtime |
|
struct tm *Plat_gmtime( const time_t *timep, struct tm *result ) |
|
{ |
|
return gmtime_r( timep, result ); |
|
} |
|
|
|
time_t Plat_timegm( struct tm *timeptr ) |
|
{ |
|
return timegm( timeptr ); |
|
} |
|
|
|
// Wraps the thread-safe versions of localtime |
|
struct tm *Plat_localtime( const time_t *timep, struct tm *result ) |
|
{ |
|
return localtime_r( timep, result ); |
|
} |
|
|
|
bool vtune( bool resume ) |
|
{ |
|
} |
|
|
|
|
|
// -------------------------------------------------------------------------------------------------- // |
|
// Memory stuff. |
|
// -------------------------------------------------------------------------------------------------- // |
|
|
|
PLATFORM_INTERFACE void Plat_DefaultAllocErrorFn( unsigned long size ) |
|
{ |
|
} |
|
|
|
typedef void (*Plat_AllocErrorFn)( unsigned long size ); |
|
Plat_AllocErrorFn g_AllocError = Plat_DefaultAllocErrorFn; |
|
|
|
PLATFORM_INTERFACE void* Plat_Alloc( unsigned long size ) |
|
{ |
|
void *pRet = g_pMemAlloc->Alloc( size ); |
|
if ( pRet ) |
|
{ |
|
return pRet; |
|
} |
|
else |
|
{ |
|
g_AllocError( size ); |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
PLATFORM_INTERFACE void* Plat_Realloc( void *ptr, unsigned long size ) |
|
{ |
|
void *pRet = g_pMemAlloc->Realloc( ptr, size ); |
|
if ( pRet ) |
|
{ |
|
return pRet; |
|
} |
|
else |
|
{ |
|
g_AllocError( size ); |
|
return 0; |
|
} |
|
} |
|
|
|
|
|
PLATFORM_INTERFACE void Plat_Free( void *ptr ) |
|
{ |
|
#if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE) |
|
g_pMemAlloc->Free( ptr ); |
|
#else |
|
free( ptr ); |
|
#endif |
|
} |
|
|
|
|
|
PLATFORM_INTERFACE void Plat_SetAllocErrorFn( Plat_AllocErrorFn fn ) |
|
{ |
|
g_AllocError = fn; |
|
} |
|
|
|
static char g_CmdLine[ 2048 ]; |
|
PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine ) |
|
{ |
|
strncpy( g_CmdLine, cmdLine, sizeof(g_CmdLine) ); |
|
g_CmdLine[ sizeof(g_CmdLine) -1 ] = 0; |
|
} |
|
|
|
PLATFORM_INTERFACE void Plat_SetCommandLineArgs( char **argv, int argc ) |
|
{ |
|
g_CmdLine[0] = 0; |
|
for ( int i = 0; i < argc; i++ ) |
|
{ |
|
strncat( g_CmdLine, argv[i], sizeof(g_CmdLine) - strlen(g_CmdLine) ); |
|
} |
|
|
|
g_CmdLine[ sizeof(g_CmdLine) -1 ] = 0; |
|
} |
|
|
|
|
|
PLATFORM_INTERFACE const tchar *Plat_GetCommandLine() |
|
{ |
|
return g_CmdLine; |
|
} |
|
|
|
PLATFORM_INTERFACE bool Is64BitOS() |
|
{ |
|
#if defined OSX |
|
return true; |
|
#elif defined LINUX |
|
FILE *pp = popen( "uname -m", "r" ); |
|
if ( pp != NULL ) |
|
{ |
|
char rgchArchString[256]; |
|
fgets( rgchArchString, sizeof( rgchArchString ), pp ); |
|
pclose( pp ); |
|
if ( !strncasecmp( rgchArchString, "x86_64", strlen( "x86_64" ) ) ) |
|
return true; |
|
} |
|
#else |
|
Assert( !"implement Is64BitOS" ); |
|
#endif |
|
return false; |
|
} |
|
|
|
|
|
bool Plat_IsInDebugSession() |
|
{ |
|
#if defined(OSX) |
|
int mib[4]; |
|
struct kinfo_proc info; |
|
size_t size; |
|
mib[0] = CTL_KERN; |
|
mib[1] = KERN_PROC; |
|
mib[2] = KERN_PROC_PID; |
|
mib[3] = getpid(); |
|
size = sizeof(info); |
|
info.kp_proc.p_flag = 0; |
|
sysctl(mib,4,&info,&size,NULL,0); |
|
bool result = ((info.kp_proc.p_flag & P_TRACED) == P_TRACED); |
|
return result; |
|
#elif defined(LINUX) |
|
char s[256]; |
|
snprintf(s, 256, "/proc/%d/cmdline", getppid()); |
|
FILE * fp = fopen(s, "r"); |
|
if (fp != NULL) |
|
{ |
|
fread(s, 256, 1, fp); |
|
fclose(fp); |
|
return (0 == strncmp(s, "gdb", 3)); |
|
} |
|
return false; |
|
#endif |
|
} |
|
|
|
|
|
|
|
void Plat_ExitProcess( int nCode ) |
|
{ |
|
_exit( nCode ); |
|
} |
|
|
|
static int s_nWatchDogTimerTimeScale = 0; |
|
static bool s_bInittedWD = false; |
|
|
|
|
|
static void InitWatchDogTimer( void ) |
|
{ |
|
if( !strstr( g_CmdLine, "-nowatchdog" ) ) |
|
{ |
|
#ifdef _DEBUG |
|
s_nWatchDogTimerTimeScale = 10; // debug is slow |
|
#else |
|
s_nWatchDogTimerTimeScale = 1; |
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
// watchdog timer support |
|
void BeginWatchdogTimer( int nSecs ) |
|
{ |
|
if (! s_bInittedWD ) |
|
{ |
|
s_bInittedWD = true; |
|
InitWatchDogTimer(); |
|
} |
|
nSecs *= s_nWatchDogTimerTimeScale; |
|
nSecs = MIN( nSecs, 5 * 60 ); // no more than 5 minutes no matter what |
|
if ( nSecs ) |
|
alarm( nSecs ); |
|
} |
|
|
|
void EndWatchdogTimer( void ) |
|
{ |
|
alarm( 0 ); |
|
} |
|
|
|
static CThreadMutex g_LocalTimeMutex; |
|
|
|
|
|
void Plat_GetLocalTime( struct tm *pNow ) |
|
{ |
|
// We just provide a wrapper on this function so we can protect access to time() everywhere. |
|
time_t ltime; |
|
time( <ime ); |
|
|
|
Plat_ConvertToLocalTime( ltime, pNow ); |
|
} |
|
|
|
void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow ) |
|
{ |
|
// Since localtime() returns a global, we need to protect against multiple threads stomping it. |
|
g_LocalTimeMutex.Lock(); |
|
|
|
time_t ltime = (time_t)nTime; |
|
tm *pTime = localtime( <ime ); |
|
if ( pTime ) |
|
*pNow = *pTime; |
|
else |
|
memset( pNow, 0, sizeof( *pNow ) ); |
|
|
|
g_LocalTimeMutex.Unlock(); |
|
} |
|
|
|
void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes ) |
|
{ |
|
g_LocalTimeMutex.Lock(); |
|
|
|
char *pStr = asctime( pTime ); |
|
strncpy( pOut, pStr, nMaxBytes ); |
|
pOut[nMaxBytes-1] = 0; |
|
|
|
g_LocalTimeMutex.Unlock(); |
|
} |
|
|
|
|
|
void Plat_gmtime( uint64 nTime, struct tm *pTime ) |
|
{ |
|
time_t tmtTime = nTime; |
|
struct tm * tmp = gmtime( &tmtTime ); |
|
* pTime = * tmp; |
|
} |
|
|
|
#ifdef LINUX |
|
size_t ApproximateProcessMemoryUsage( void ) |
|
{ |
|
int nRet = 0; |
|
FILE *pFile = fopen( "/proc/self/statm", "r" ); |
|
if ( pFile ) |
|
{ |
|
int nSize, nTotalProgramSize, nResident, nResidentSetSize, nShare, nSharedPagesTotal, nDummy0; |
|
if ( fscanf( pFile, "%d %d %d %d %d %d %d", &nSize, &nTotalProgramSize, &nResident, &nResidentSetSize, &nShare, &nSharedPagesTotal, &nDummy0 ) ) |
|
{ |
|
nRet = 4096 * nSize; |
|
} |
|
fclose( pFile ); |
|
} |
|
return nRet; |
|
} |
|
#else |
|
|
|
size_t ApproximateProcessMemoryUsage( void ) |
|
{ |
|
return 0; |
|
} |
|
|
|
#endif
|
|
|