Leaked source code of windows server 2003
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.

260 lines
5.9 KiB

  1. #include "precomp.h"
  2. #include <oprahcom.h>
  3. #include <regentry.h>
  4. #include "mperror.h"
  5. #include <sehcall.h>
  6. #define LEGACY_DIVISOR 8
  7. extern "C" WORD _cdecl is_cyrix(void);
  8. extern "C" DWORD _cdecl get_nxcpu_type(void);
  9. #ifndef _M_IX86
  10. DWORD WINAPI CallWithSEH(EXCEPTPROC pfn, void *pv, INEXCEPTION InException)
  11. {
  12. // we don't have a native version of SEH for the alpha,
  13. // use __try and __except
  14. pfn(pv);
  15. return 0;
  16. }
  17. #endif
  18. #ifdef _M_IX86
  19. DWORD NMINTERNAL FindTSC (LPVOID pvRefData)
  20. {
  21. _asm
  22. {
  23. mov eax,1
  24. _emit 00Fh ;; CPUID
  25. _emit 0A2h
  26. // The ref data is 2 DWORDS, the first is the flags,
  27. // the second the family
  28. mov ecx,pvRefData
  29. mov [ecx],edx
  30. mov [ecx][4],eax
  31. }
  32. return 1;
  33. }
  34. DWORD NMINTERNAL NoCPUID (LPEXCEPTION_RECORD per,PCONTEXT pctx)
  35. {
  36. return 0;
  37. }
  38. //
  39. // GetProcessorSpeed(dwFamily)
  40. //
  41. // get the processor speed in MHz, only works on Pentium or better
  42. // machines.
  43. //
  44. // Will put 3, or 4 in dwFamily for 386/486, but no speed.
  45. // returns speed and family for 586+
  46. //
  47. // - thanks to toddla, modified by mikeg
  48. //
  49. int NMINTERNAL GetProcessorSpeed(int *pdwFamily)
  50. {
  51. SYSTEM_INFO si;
  52. __int64 start, end, freq;
  53. int flags,family;
  54. int time;
  55. int clocks;
  56. DWORD oldclass;
  57. HANDLE hprocess;
  58. int pRef[2];
  59. ZeroMemory(&si, sizeof(si));
  60. GetSystemInfo(&si);
  61. //Set the family. If wProcessorLevel is not specified, dig it out of dwProcessorType
  62. //Because wProcessor level is not implemented on Win95
  63. if (si.wProcessorLevel) {
  64. *pdwFamily=si.wProcessorLevel;
  65. }else {
  66. //Ok, we're on Win95
  67. switch (si.dwProcessorType) {
  68. case PROCESSOR_INTEL_386:
  69. *pdwFamily=3;
  70. break;
  71. case PROCESSOR_INTEL_486:
  72. *pdwFamily=4;
  73. break;
  74. default:
  75. *pdwFamily=0;
  76. break;
  77. }
  78. }
  79. //
  80. // make sure this is a INTEL Pentium (or clone) or higher.
  81. //
  82. if (si.wProcessorArchitecture != PROCESSOR_ARCHITECTURE_INTEL)
  83. return 0;
  84. if (si.dwProcessorType < PROCESSOR_INTEL_PENTIUM)
  85. return 0;
  86. //
  87. // see if this chip supports rdtsc before using it.
  88. //
  89. if (!CallWithSEH (FindTSC, pRef, NoCPUID)) {
  90. flags=0;
  91. } else {
  92. // The ref data is 2 DWORDS, the first is the flags,
  93. // the second the family. Pull them out and use them
  94. flags=pRef[0];
  95. family=pRef[1];
  96. }
  97. if (!(flags & 0x10))
  98. return 0;
  99. //If we don't have a family, set it now
  100. //Family is bits 11:8 of eax from CPU, with eax=1
  101. if (!(*pdwFamily)) {
  102. *pdwFamily=(family& 0x0F00) >> 8;
  103. }
  104. hprocess = GetCurrentProcess();
  105. oldclass = GetPriorityClass(hprocess);
  106. SetPriorityClass(hprocess, REALTIME_PRIORITY_CLASS);
  107. Sleep(10);
  108. QueryPerformanceFrequency((LARGE_INTEGER*)&freq);
  109. QueryPerformanceCounter((LARGE_INTEGER*)&start);
  110. _asm
  111. {
  112. _emit 0Fh ;; RDTSC
  113. _emit 31h
  114. mov ecx,100000
  115. x: dec ecx
  116. jnz x
  117. mov ebx,eax
  118. _emit 0Fh ;; RDTSC
  119. _emit 31h
  120. sub eax,ebx
  121. mov dword ptr clocks[0],eax
  122. }
  123. QueryPerformanceCounter((LARGE_INTEGER*)&end);
  124. SetPriorityClass(hprocess, oldclass);
  125. time = MulDiv((int)(end-start),1000000,(int)freq);
  126. return (clocks + time/2) / time;
  127. }
  128. HRESULT NMINTERNAL GetNormalizedCPUSpeed (int *pdwNormalizedSpeed, int *dwFamily)
  129. {
  130. int dwProcessorSpeed;
  131. dwProcessorSpeed=GetProcessorSpeed (dwFamily);
  132. *pdwNormalizedSpeed=dwProcessorSpeed;
  133. if (*dwFamily > 5) {
  134. //Ok, TWO things.
  135. // ONE DO NOT DO FP!
  136. // Two for the same Mhz assume a 686 is 1.3 times as fast as a 586 and a 786 is 1.6 times, etc.
  137. *pdwNormalizedSpeed=(ULONG) (((10+3*(*dwFamily-5))*dwProcessorSpeed)/10);
  138. }
  139. if (*dwFamily < 5) {
  140. //bugbug until we have 386/486 timing code, assume
  141. //486=50,386=37
  142. if (*dwFamily > 3) {
  143. //Cyrix, (5x86)? check before making default assignment
  144. if (is_cyrix()) {
  145. if (*pdwNormalizedSpeed==0) {
  146. *dwFamily=5;
  147. *pdwNormalizedSpeed=100;
  148. return hrSuccess;
  149. }
  150. }
  151. }
  152. *pdwNormalizedSpeed= (*dwFamily*100)/LEGACY_DIVISOR;
  153. if (get_nxcpu_type ()) {
  154. //Double the perceived value on a NexGen
  155. *pdwNormalizedSpeed *=2;
  156. }
  157. }
  158. return hrSuccess;
  159. }
  160. #endif //_M_IX86
  161. BOOL WINAPI IsFloatingPointEmulated(void)
  162. {
  163. long lRegValue;
  164. SYSTEM_INFO si;
  165. OSVERSIONINFO osi;
  166. BOOL fEmulation, bNT;
  167. // are we a Pentium
  168. ZeroMemory(&si, sizeof(si));
  169. GetSystemInfo(&si);
  170. if (si.dwProcessorType != PROCESSOR_INTEL_PENTIUM)
  171. {
  172. return FALSE;
  173. }
  174. // Which OS: NT or 95 ?
  175. ZeroMemory(&osi, sizeof(osi));
  176. osi.dwOSVersionInfoSize = sizeof(osi);
  177. GetVersionEx(&osi);
  178. bNT = (osi.dwPlatformId == VER_PLATFORM_WIN32_NT);
  179. // Windows NT
  180. if (bNT)
  181. {
  182. RegEntry re(TEXT("System\\CurrentControlSet\\Control\\Session Manager"),
  183. HKEY_LOCAL_MACHINE, FALSE);
  184. // try to get a definitive answer from the registry
  185. lRegValue = re.GetNumber(TEXT("ForceNpxEmulation"), -1);
  186. // registry: 0: no
  187. // 1: conditional (not definitive!)
  188. // 2: yes
  189. if (lRegValue == 2)
  190. {
  191. return TRUE;
  192. }
  193. // we could load "IsProcessorFeaturePresent from kernel32.dll,
  194. // but the version that shipped with NT 4 has a bug in it that
  195. // returns the exact opposite of what it should be. It was
  196. // fixed in NT 5. Since this API isn't the same across platforms,
  197. // we won't use it.
  198. return FALSE;
  199. }
  200. // Windows 95 - to be added later
  201. return FALSE;
  202. }