Counter Strike : Global Offensive Source Code
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.

158 lines
3.3 KiB

  1. //========= Copyright 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: determine CPU speed under linux
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <sys/types.h>
  10. #include <sys/sysctl.h>
  11. #include <sys/time.h>
  12. #include <unistd.h>
  13. #include <tier0/platform.h>
  14. #include <errno.h>
  15. class TimeVal
  16. {
  17. public:
  18. TimeVal() {}
  19. TimeVal& operator=(const TimeVal &val) { m_TimeVal = val.m_TimeVal; return *this; }
  20. inline double operator-(const TimeVal &left)
  21. {
  22. uint64 left_us = (uint64) left.m_TimeVal.tv_sec * 1000000 + left.m_TimeVal.tv_usec;
  23. uint64 right_us = (uint64) m_TimeVal.tv_sec * 1000000 + m_TimeVal.tv_usec;
  24. uint64 diff_us = right_us - left_us;
  25. return diff_us * ( 1.0 / 1000000.0 );
  26. }
  27. timeval m_TimeVal;
  28. };
  29. // Compute the positive difference between two 64 bit numbers.
  30. static inline uint64 diff(uint64 v1, uint64 v2)
  31. {
  32. // uint64 d = v1 - v2;
  33. // if (d >= 0) return d; else return -d;
  34. return (v1 >= v2 ? v1 - v2 : v2 - v1);
  35. }
  36. #ifdef OSX
  37. uint64 GetCPUFreqFromPROC()
  38. {
  39. int mib[2] = {CTL_HW, HW_CPU_FREQ};
  40. uint64 frequency = 0;
  41. size_t len = sizeof(frequency);
  42. if (sysctl(mib, 2, &frequency, &len, NULL, 0) == -1)
  43. return 0;
  44. return frequency;
  45. }
  46. #else
  47. uint64 GetCPUFreqFromPROC()
  48. {
  49. double mhz = 0;
  50. char line[1024], *s, search_str[] = "cpu MHz";
  51. FILE *fp;
  52. /* open proc/cpuinfo */
  53. if ((fp = fopen("/proc/cpuinfo", "r")) == NULL)
  54. {
  55. return 0;
  56. }
  57. /* ignore all lines until we reach MHz information */
  58. while (fgets(line, 1024, fp) != NULL)
  59. {
  60. if (strstr(line, search_str) != NULL)
  61. {
  62. /* ignore all characters in line up to : */
  63. for (s = line; *s && (*s != ':'); ++s)
  64. ;
  65. /* get MHz number */
  66. if (*s && (sscanf(s+1, "%lf", &mhz) == 1))
  67. break;
  68. }
  69. }
  70. if (fp!=NULL) fclose(fp);
  71. return (uint64)(mhz*1000000);
  72. }
  73. #endif
  74. uint64 CalculateCPUFreq()
  75. {
  76. #ifdef LINUX
  77. char const *pFreq = getenv("CPU_MHZ");
  78. if ( pFreq )
  79. {
  80. uint64 retVal = 1000000;
  81. return retVal * atoi( pFreq );
  82. }
  83. #endif
  84. // Compute the period. Loop until we get 3 consecutive periods that
  85. // are the same to within a small error. The error is chosen
  86. // to be +/- 0.02% on a P-200.
  87. const uint64 error = 40000;
  88. const int max_iterations = 600;
  89. int count;
  90. uint64 period, period1 = error * 2, period2 = 0, period3 = 0;
  91. for (count = 0; count < max_iterations; count++)
  92. {
  93. TimeVal start_time, end_time;
  94. uint64 start_tsc, end_tsc;
  95. gettimeofday( &start_time.m_TimeVal, 0 );
  96. start_tsc = Plat_Rdtsc();
  97. usleep( 5000 ); // sleep for 5 msec
  98. gettimeofday( &end_time.m_TimeVal, 0 );
  99. end_tsc = Plat_Rdtsc();
  100. period3 = ( end_tsc - start_tsc ) / ( end_time - start_time );
  101. if (diff( period1, period2 ) <= error &&
  102. diff( period2, period3 ) <= error &&
  103. diff( period1, period3 ) <= error )
  104. {
  105. break;
  106. }
  107. period1 = period2;
  108. period2 = period3;
  109. }
  110. if ( count == max_iterations )
  111. {
  112. return GetCPUFreqFromPROC(); // fall back to /proc
  113. }
  114. // Set the period to the average period measured.
  115. period = ( period1 + period2 + period3 ) / 3;
  116. // Some Pentiums have broken TSCs that increment very
  117. // slowly or unevenly.
  118. if ( period < 10000000 )
  119. {
  120. return GetCPUFreqFromPROC(); // fall back to /proc
  121. }
  122. return period;
  123. }