Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "pch_tier0.h"
  8. #include "tier0/platform.h"
  9. #include "tier0/memalloc.h"
  10. #include "tier0/dbg.h"
  11. #include "tier0/threadtools.h"
  12. #include <sys/time.h>
  13. #include <unistd.h>
  14. #ifdef OSX
  15. #include <sys/sysctl.h>
  16. #include <mach/mach.h>
  17. #include <mach/mach_time.h>
  18. #endif
  19. static bool g_bBenchmarkMode = false;
  20. static double g_FakeBenchmarkTime = 0;
  21. static double g_FakeBenchmarkTimeInc = 1.0 / 66.0;
  22. bool Plat_IsInBenchmarkMode()
  23. {
  24. return g_bBenchmarkMode;
  25. }
  26. void Plat_SetBenchmarkMode( bool bBenchmark )
  27. {
  28. g_bBenchmarkMode = bBenchmark;
  29. }
  30. #ifdef OSX
  31. static uint64 start_time = 0;
  32. static mach_timebase_info_data_t sTimebaseInfo;
  33. static double conversion = 0.0;
  34. void InitTime()
  35. {
  36. start_time = mach_absolute_time();
  37. mach_timebase_info(&sTimebaseInfo);
  38. conversion = 1e-9 * (double) sTimebaseInfo.numer / (double) sTimebaseInfo.denom;
  39. }
  40. uint64 Plat_GetClockStart()
  41. {
  42. if ( !start_time )
  43. {
  44. InitTime();
  45. }
  46. return start_time * conversion;
  47. }
  48. double Plat_FloatTime()
  49. {
  50. if ( g_bBenchmarkMode )
  51. {
  52. g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc;
  53. return g_FakeBenchmarkTime;
  54. }
  55. if ( !start_time )
  56. {
  57. InitTime();
  58. }
  59. uint64 now = mach_absolute_time();
  60. return ( now - start_time ) * conversion;
  61. }
  62. #else
  63. static int secbase = 0;
  64. void InitTime( struct timeval &tp )
  65. {
  66. secbase = tp.tv_sec;
  67. }
  68. uint64 Plat_GetClockStart()
  69. {
  70. if ( !secbase )
  71. {
  72. struct timeval tp;
  73. gettimeofday( &tp, NULL );
  74. InitTime( tp );
  75. }
  76. return secbase;
  77. }
  78. double Plat_FloatTime()
  79. {
  80. if ( g_bBenchmarkMode )
  81. {
  82. g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc;
  83. return g_FakeBenchmarkTime;
  84. }
  85. struct timeval tp;
  86. gettimeofday( &tp, NULL );
  87. if ( !secbase )
  88. {
  89. InitTime( tp );
  90. return ( tp.tv_usec / 1000000.0 );
  91. }
  92. return (( tp.tv_sec - secbase ) + tp.tv_usec / 1000000.0 );
  93. }
  94. #endif
  95. uint32 Plat_MSTime()
  96. {
  97. if ( g_bBenchmarkMode )
  98. {
  99. g_FakeBenchmarkTime += g_FakeBenchmarkTimeInc;
  100. return (unsigned long)(g_FakeBenchmarkTime * 1000.0);
  101. }
  102. struct timeval tp;
  103. static int secbase = 0;
  104. gettimeofday( &tp, NULL );
  105. if ( !secbase )
  106. {
  107. secbase = tp.tv_sec;
  108. return ( tp.tv_usec / 1000.0 );
  109. }
  110. return (unsigned long)(( tp.tv_sec - secbase )*1000.0 + tp.tv_usec / 1000.0 );
  111. }
  112. // Wraps the thread-safe versions of asctime. buf must be at least 26 bytes
  113. char *Plat_asctime( const struct tm *tm, char *buf, size_t bufsize )
  114. {
  115. return asctime_r( tm, buf );
  116. }
  117. // Wraps the thread-safe versions of ctime. buf must be at least 26 bytes
  118. char *Plat_ctime( const time_t *timep, char *buf, size_t bufsize )
  119. {
  120. return ctime_r( timep, buf );
  121. }
  122. // Wraps the thread-safe versions of gmtime
  123. struct tm *Plat_gmtime( const time_t *timep, struct tm *result )
  124. {
  125. return gmtime_r( timep, result );
  126. }
  127. time_t Plat_timegm( struct tm *timeptr )
  128. {
  129. return timegm( timeptr );
  130. }
  131. // Wraps the thread-safe versions of localtime
  132. struct tm *Plat_localtime( const time_t *timep, struct tm *result )
  133. {
  134. return localtime_r( timep, result );
  135. }
  136. bool vtune( bool resume )
  137. {
  138. }
  139. // -------------------------------------------------------------------------------------------------- //
  140. // Memory stuff.
  141. // -------------------------------------------------------------------------------------------------- //
  142. PLATFORM_INTERFACE void Plat_DefaultAllocErrorFn( unsigned long size )
  143. {
  144. }
  145. typedef void (*Plat_AllocErrorFn)( unsigned long size );
  146. Plat_AllocErrorFn g_AllocError = Plat_DefaultAllocErrorFn;
  147. PLATFORM_INTERFACE void* Plat_Alloc( unsigned long size )
  148. {
  149. void *pRet = g_pMemAlloc->Alloc( size );
  150. if ( pRet )
  151. {
  152. return pRet;
  153. }
  154. else
  155. {
  156. g_AllocError( size );
  157. return 0;
  158. }
  159. }
  160. PLATFORM_INTERFACE void* Plat_Realloc( void *ptr, unsigned long size )
  161. {
  162. void *pRet = g_pMemAlloc->Realloc( ptr, size );
  163. if ( pRet )
  164. {
  165. return pRet;
  166. }
  167. else
  168. {
  169. g_AllocError( size );
  170. return 0;
  171. }
  172. }
  173. PLATFORM_INTERFACE void Plat_Free( void *ptr )
  174. {
  175. #if !defined(STEAM) && !defined(NO_MALLOC_OVERRIDE)
  176. g_pMemAlloc->Free( ptr );
  177. #else
  178. free( ptr );
  179. #endif
  180. }
  181. PLATFORM_INTERFACE void Plat_SetAllocErrorFn( Plat_AllocErrorFn fn )
  182. {
  183. g_AllocError = fn;
  184. }
  185. static char g_CmdLine[ 2048 ];
  186. PLATFORM_INTERFACE void Plat_SetCommandLine( const char *cmdLine )
  187. {
  188. strncpy( g_CmdLine, cmdLine, sizeof(g_CmdLine) );
  189. g_CmdLine[ sizeof(g_CmdLine) -1 ] = 0;
  190. }
  191. PLATFORM_INTERFACE void Plat_SetCommandLineArgs( char **argv, int argc )
  192. {
  193. g_CmdLine[0] = 0;
  194. for ( int i = 0; i < argc; i++ )
  195. {
  196. strncat( g_CmdLine, argv[i], sizeof(g_CmdLine) - strlen(g_CmdLine) );
  197. }
  198. g_CmdLine[ sizeof(g_CmdLine) -1 ] = 0;
  199. }
  200. PLATFORM_INTERFACE const tchar *Plat_GetCommandLine()
  201. {
  202. return g_CmdLine;
  203. }
  204. PLATFORM_INTERFACE bool Is64BitOS()
  205. {
  206. #if defined OSX
  207. return true;
  208. #elif defined LINUX
  209. FILE *pp = popen( "uname -m", "r" );
  210. if ( pp != NULL )
  211. {
  212. char rgchArchString[256];
  213. fgets( rgchArchString, sizeof( rgchArchString ), pp );
  214. pclose( pp );
  215. if ( !strncasecmp( rgchArchString, "x86_64", strlen( "x86_64" ) ) )
  216. return true;
  217. }
  218. #else
  219. Assert( !"implement Is64BitOS" );
  220. #endif
  221. return false;
  222. }
  223. bool Plat_IsInDebugSession()
  224. {
  225. #if defined(OSX)
  226. int mib[4];
  227. struct kinfo_proc info;
  228. size_t size;
  229. mib[0] = CTL_KERN;
  230. mib[1] = KERN_PROC;
  231. mib[2] = KERN_PROC_PID;
  232. mib[3] = getpid();
  233. size = sizeof(info);
  234. info.kp_proc.p_flag = 0;
  235. sysctl(mib,4,&info,&size,NULL,0);
  236. bool result = ((info.kp_proc.p_flag & P_TRACED) == P_TRACED);
  237. return result;
  238. #elif defined(LINUX)
  239. char s[256];
  240. snprintf(s, 256, "/proc/%d/cmdline", getppid());
  241. FILE * fp = fopen(s, "r");
  242. if (fp != NULL)
  243. {
  244. fread(s, 256, 1, fp);
  245. fclose(fp);
  246. return (0 == strncmp(s, "gdb", 3));
  247. }
  248. return false;
  249. #endif
  250. }
  251. void Plat_ExitProcess( int nCode )
  252. {
  253. _exit( nCode );
  254. }
  255. static int s_nWatchDogTimerTimeScale = 0;
  256. static bool s_bInittedWD = false;
  257. static void InitWatchDogTimer( void )
  258. {
  259. if( !strstr( g_CmdLine, "-nowatchdog" ) )
  260. {
  261. #ifdef _DEBUG
  262. s_nWatchDogTimerTimeScale = 10; // debug is slow
  263. #else
  264. s_nWatchDogTimerTimeScale = 1;
  265. #endif
  266. }
  267. }
  268. // watchdog timer support
  269. void BeginWatchdogTimer( int nSecs )
  270. {
  271. if (! s_bInittedWD )
  272. {
  273. s_bInittedWD = true;
  274. InitWatchDogTimer();
  275. }
  276. nSecs *= s_nWatchDogTimerTimeScale;
  277. nSecs = MIN( nSecs, 5 * 60 ); // no more than 5 minutes no matter what
  278. if ( nSecs )
  279. alarm( nSecs );
  280. }
  281. void EndWatchdogTimer( void )
  282. {
  283. alarm( 0 );
  284. }
  285. static CThreadMutex g_LocalTimeMutex;
  286. void Plat_GetLocalTime( struct tm *pNow )
  287. {
  288. // We just provide a wrapper on this function so we can protect access to time() everywhere.
  289. time_t ltime;
  290. time( &ltime );
  291. Plat_ConvertToLocalTime( ltime, pNow );
  292. }
  293. void Plat_ConvertToLocalTime( uint64 nTime, struct tm *pNow )
  294. {
  295. // Since localtime() returns a global, we need to protect against multiple threads stomping it.
  296. g_LocalTimeMutex.Lock();
  297. time_t ltime = (time_t)nTime;
  298. tm *pTime = localtime( &ltime );
  299. if ( pTime )
  300. *pNow = *pTime;
  301. else
  302. memset( pNow, 0, sizeof( *pNow ) );
  303. g_LocalTimeMutex.Unlock();
  304. }
  305. void Plat_GetTimeString( struct tm *pTime, char *pOut, int nMaxBytes )
  306. {
  307. g_LocalTimeMutex.Lock();
  308. char *pStr = asctime( pTime );
  309. strncpy( pOut, pStr, nMaxBytes );
  310. pOut[nMaxBytes-1] = 0;
  311. g_LocalTimeMutex.Unlock();
  312. }
  313. void Plat_gmtime( uint64 nTime, struct tm *pTime )
  314. {
  315. time_t tmtTime = nTime;
  316. struct tm * tmp = gmtime( &tmtTime );
  317. * pTime = * tmp;
  318. }
  319. #ifdef LINUX
  320. size_t ApproximateProcessMemoryUsage( void )
  321. {
  322. int nRet = 0;
  323. FILE *pFile = fopen( "/proc/self/statm", "r" );
  324. if ( pFile )
  325. {
  326. int nSize, nTotalProgramSize, nResident, nResidentSetSize, nShare, nSharedPagesTotal, nDummy0;
  327. if ( fscanf( pFile, "%d %d %d %d %d %d %d", &nSize, &nTotalProgramSize, &nResident, &nResidentSetSize, &nShare, &nSharedPagesTotal, &nDummy0 ) )
  328. {
  329. nRet = 4096 * nSize;
  330. }
  331. fclose( pFile );
  332. }
  333. return nRet;
  334. }
  335. #else
  336. size_t ApproximateProcessMemoryUsage( void )
  337. {
  338. return 0;
  339. }
  340. #endif