source: trunk/src/kernel32/cpu.cpp@ 9880

Last change on this file since 9880 was 9880, checked in by sandervl, 22 years ago

Check for invalid data while measuring the CPU speed. DosTmrQueryTime isn't very reliable (on laptops)

File size: 7.0 KB
Line 
1/* $Id: cpu.cpp,v 1.14 2003-02-28 15:37:21 sandervl Exp $ */
2/*
3 * Odin win32 CPU apis
4 *
5 * Copyright 1999 Sander van Leeuwen (sandervl@xs4all.nl)
6 *
7 * Based on Wine Code (991031: misc\cpu.c)
8 *
9 * Copyright 1995,1997 Morten Welinder
10 * Copyright 1997-1998 Marcus Meissner
11 */
12
13#include <os2win.h>
14#include <ctype.h>
15#include <string.h>
16#include "winreg.h"
17#include "global.h"
18#include "winnt.h"
19#include "winerror.h"
20#include "winreg.h"
21#include "debugtools.h"
22#include <cpuhlp.h>
23
24#define DBG_LOCALLOG DBG_cpu
25#include "dbglocal.h"
26
27DEFAULT_DEBUG_CHANNEL(CPU)
28
29static BYTE PF[64] = {0,};
30static nrCPUs = 1;
31static SYSTEM_INFO cachedsi = {0};
32
33//******************************************************************************
34//******************************************************************************
35void InitSystemInfo(int nrcpus)
36{
37 SYSTEM_INFO si;
38
39 nrCPUs = nrcpus;
40 GetSystemInfo(&si);
41}
42/***********************************************************************
43 * GetSystemInfo [KERNELL32.404]
44 *
45 * Gets the current system information.
46 *
47 * On the first call it reads cached values, so it doesn't have to determine
48 * them repeatedly. On Linux, the /proc/cpuinfo special file is used.
49 *
50 * It creates a registry subhierarchy, looking like:
51 * \HARDWARE\DESCRIPTION\System\CentralProcessor\<processornumber>\
52 * Identifier (CPU x86)
53 * Note that there is a hierarchy for every processor installed, so this
54 * supports multiprocessor systems. This is done like Win95 does it, I think.
55 *
56 * It also creates a cached flag array for IsProcessorFeaturePresent().
57 *
58 * RETURNS
59 * nothing, really
60 */
61VOID WINAPI GetSystemInfo(LPSYSTEM_INFO si) /* [out] system information */
62{
63 HKEY xhkey=0,hkey;
64 HKEY fpukey=0, xhfpukey;
65 char buf[20];
66 DWORD features, signature;
67 static int cache = 0;
68
69 if(!si) {
70 dprintf(("GetSystemInfo -> si == NULL!!"));
71 SetLastError(ERROR_INVALID_PARAMETER);
72 return;
73 }
74 if (cache) {
75 memcpy(si,&cachedsi,sizeof(*si));
76 return;
77 }
78 memset(PF,0,sizeof(PF));
79
80 /* choose sensible defaults ...
81 * FIXME: perhaps overrideable with precompiler flags?
82 */
83 cachedsi.u.x.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
84 cachedsi.dwPageSize = 4096;
85
86 /* FIXME: better values for the two entries below... */
87 cachedsi.lpMinimumApplicationAddress = (void *)0x00400000;
88 cachedsi.lpMaximumApplicationAddress = (void *)0x7FFFFFFF;
89 cachedsi.dwActiveProcessorMask = 1;
90 cachedsi.dwNumberOfProcessors = nrCPUs;
91 cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
92 cachedsi.dwAllocationGranularity = 0x10000;
93 cachedsi.wProcessorLevel = 3; /* 386 */
94 cachedsi.wProcessorRevision = 0;
95
96 cache = 1; /* even if there is no more info, we now have a cacheentry */
97 memcpy(si,&cachedsi,sizeof(*si));
98
99 /* Hmm, reasonable processor feature defaults? */
100
101 /* Create this registry key for all systems */
102 if (RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\CentralProcessor",&hkey)!=ERROR_SUCCESS) {
103 dprintf(("Unable to register CPU information\n"));
104 }
105
106 if(SupportsCPUID())
107 {
108 for(int i=0;i<cachedsi.dwNumberOfProcessors;i++)
109 {
110 // Create a new processor subkey
111 sprintf(buf,"%d",i);
112 if (xhkey)
113 RegCloseKey(xhkey);
114 RegCreateKeyA(hkey,buf,&xhkey);
115
116 signature = GetCPUSignature();
117
118 switch ((signature >> 8)&0xf) {
119 case 3: cachedsi.dwProcessorType = PROCESSOR_INTEL_386;
120 break;
121 case 4: cachedsi.dwProcessorType = PROCESSOR_INTEL_486;
122 break;
123 case 5: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
124 break;
125 case 6: cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
126 break;
127 default:
128 break;
129 }
130 cachedsi.wProcessorRevision = signature & 0xff;
131 cachedsi.wProcessorLevel = (signature >> 8)&0xf;
132
133 /* set the CPU type of the current processor */
134 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
135 if (xhkey) {
136 RegSetValueExA(xhkey,"Identifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
137 memset(buf, 0, sizeof(buf));
138 GetCPUVendorString(buf);
139 RegSetValueExA(xhkey,"VendorIdentifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
140#ifdef __WIN32OS2__
141 if(i==0) {
142 DWORD mhz;
143 features = GetCPUFeatures();
144 if(features & CPUID_TIME_STAMP_COUNTER) {
145 LARGE_INTEGER tsc1, tsc2, freq, time1, time2;
146 double clockticks, millisec, frequency, tmp, tmp1, mhertz;
147
148 QueryPerformanceFrequency(&freq);
149
150 GetTSC((LONG *)&tsc1.LowPart, &tsc1.HighPart);
151 QueryPerformanceCounter(&time1);
152
153 Sleep(32); //sleep for about 32 ms
154
155 GetTSC((LONG *)&tsc2.LowPart, &tsc2.HighPart);
156 QueryPerformanceCounter(&time2);
157 tmp = (double)time2.LowPart + (double)time2.HighPart*4.0*1024.0*1024.0;
158 tmp1 = (double)time1.LowPart + (double)time1.HighPart*4.0*1024.0*1024.0;
159 millisec = tmp - tmp1;
160
161 frequency= (double)freq.LowPart;
162 frequency= frequency / 1000.0;
163 millisec = millisec / frequency;
164
165 tmp = (double)tsc2.LowPart + (double)tsc2.HighPart*4.0*1024.0*1024.0;
166 tmp1 = (double)tsc1.LowPart + (double)tsc1.HighPart*4.0*1024.0*1024.0;
167 clockticks = tmp - tmp1;
168 if(millisec > 0)
169 {//make sure we have something valid here
170 tmp = 1000 / millisec;
171 clockticks = clockticks * tmp; //ticks per second
172 mhertz = clockticks / 1000000.0;
173 mhz = (DWORD)mhertz;
174 }
175 else mhz = 500;
176 }
177 else mhz = 500;
178 RegSetValueExA(xhkey,"~Mhz",0,REG_DWORD, (LPBYTE)&mhz, sizeof(DWORD));
179 }
180#endif
181 }
182//TODO: FPU fdiv bug
183#if 0
184 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
185 if (!lstrncmpiA(value,"yes",3))
186 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
187
188 continue;
189 }
190#endif
191 features = GetCPUFeatures();
192 if (features & CPUID_CMPXCHG8B_INSTRUCTION)
193 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
194 if (features & CPUID_MMX)
195 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
196
197 //Create FPU key if one is present
198 if (features & CPUID_FPU_PRESENT) {
199 if (i == 0) {
200 if(RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\FloatingPointProcessor",&fpukey)!=ERROR_SUCCESS)
201 dprintf(("Unable to register FPU information\n"));
202 }
203 // Create a new processor subkey
204 if(fpukey) {
205 sprintf(buf,"%d",i);
206 RegCreateKeyA(fpukey,buf,&xhfpukey);
207 }
208 }
209
210 } //for each cpu
211 }
212 memcpy(si,&cachedsi,sizeof(*si));
213
214 if (xhkey)
215 RegCloseKey(xhkey);
216 if (hkey)
217 RegCloseKey(hkey);
218 if (xhfpukey)
219 RegCloseKey(xhfpukey);
220 if (fpukey)
221 RegCloseKey(fpukey);
222
223}
224
225
226/***********************************************************************
227 * IsProcessorFeaturePresent [KERNELL32.880]
228 * RETURNS:
229 * TRUE if processorfeature present
230 * FALSE otherwise
231 */
232BOOL WINAPI IsProcessorFeaturePresent (DWORD feature) /* [in] feature number, see PF_ defines */
233{
234 SYSTEM_INFO si;
235 GetSystemInfo (&si); /* To ensure the information is loaded and cached */
236
237 if (feature < 64) {
238 dprintf(("IsProcessorFeaturePresent %x -> %x", feature, PF[feature]));
239 return PF[feature];
240 }
241 else
242 return FALSE;
243}
244//******************************************************************************
245//******************************************************************************
Note: See TracBrowser for help on using the repository browser.