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

Last change on this file since 21388 was 21343, checked in by vladest, 16 years ago
  1. Increased number of handles (4096 is not enougth for some Flash animations)
  2. Added CPU cycles couter for more accurate profiling
File size: 7.1 KB
Line 
1/* $Id: cpu.cpp,v 1.15 2004-02-20 10:05:39 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 cachedsi.dwProcessorType = PROCESSOR_INTEL_PENTIUM;
129 break;
130 }
131 cachedsi.wProcessorRevision = signature & 0xff;
132 cachedsi.wProcessorLevel = (signature >> 8)&0xf;
133
134 /* set the CPU type of the current processor */
135 sprintf(buf,"CPU %ld",cachedsi.dwProcessorType);
136 if (xhkey) {
137 RegSetValueExA(xhkey,"Identifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
138 memset(buf, 0, sizeof(buf));
139 GetCPUVendorString(buf);
140 RegSetValueExA(xhkey,"VendorIdentifier",0,REG_SZ,(LPBYTE)buf,strlen(buf));
141#ifdef __WIN32OS2__
142 if(i==0) {
143 DWORD mhz;
144 features = GetCPUFeatures();
145 if(features & CPUID_TIME_STAMP_COUNTER) {
146 LARGE_INTEGER tsc1, tsc2, freq, time1, time2;
147 double clockticks, millisec, frequency, tmp, tmp1, mhertz;
148
149 QueryPerformanceFrequency(&freq);
150
151 GetTSC((LONG *)&tsc1.LowPart, &tsc1.HighPart);
152 QueryPerformanceCounter(&time1);
153
154 Sleep(32); //sleep for about 32 ms
155
156 GetTSC((LONG *)&tsc2.LowPart, &tsc2.HighPart);
157 QueryPerformanceCounter(&time2);
158 tmp = (double)time2.LowPart + (double)time2.HighPart*4.0*1024.0*1024.0;
159 tmp1 = (double)time1.LowPart + (double)time1.HighPart*4.0*1024.0*1024.0;
160 millisec = tmp - tmp1;
161
162 frequency= (double)freq.LowPart;
163 frequency= frequency / 1000.0;
164 millisec = millisec / frequency;
165
166 tmp = (double)tsc2.LowPart + (double)tsc2.HighPart*4.0*1024.0*1024.0;
167 tmp1 = (double)tsc1.LowPart + (double)tsc1.HighPart*4.0*1024.0*1024.0;
168 clockticks = tmp - tmp1;
169 if(millisec > 0)
170 {//make sure we have something valid here
171 tmp = 1000 / millisec;
172 clockticks = clockticks * tmp; //ticks per second
173 mhertz = clockticks / 1000000.0;
174 mhz = (DWORD)mhertz;
175 }
176 else mhz = 500;
177 }
178 else mhz = 500;
179 RegSetValueExA(xhkey,"~Mhz",0,REG_DWORD, (LPBYTE)&mhz, sizeof(DWORD));
180 }
181#endif
182 }
183//TODO: FPU fdiv bug
184#if 0
185 if (!lstrncmpiA(line,"fdiv_bug",strlen("fdiv_bug"))) {
186 if (!lstrncmpiA(value,"yes",3))
187 PF[PF_FLOATING_POINT_PRECISION_ERRATA] = TRUE;
188
189 continue;
190 }
191#endif
192 features = GetCPUFeatures();
193 if (features & CPUID_CMPXCHG8B_INSTRUCTION)
194 PF[PF_COMPARE_EXCHANGE_DOUBLE] = TRUE;
195 if (features & CPUID_MMX)
196 PF[PF_MMX_INSTRUCTIONS_AVAILABLE] = TRUE;
197
198 //Create FPU key if one is present
199 if (features & CPUID_FPU_PRESENT) {
200 if (i == 0) {
201 if(RegCreateKeyA(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\FloatingPointProcessor",&fpukey)!=ERROR_SUCCESS)
202 dprintf(("Unable to register FPU information\n"));
203 }
204 // Create a new processor subkey
205 if(fpukey) {
206 sprintf(buf,"%d",i);
207 RegCreateKeyA(fpukey,buf,&xhfpukey);
208 }
209 }
210
211 } //for each cpu
212 }
213 memcpy(si,&cachedsi,sizeof(*si));
214
215 if (xhkey)
216 RegCloseKey(xhkey);
217 if (hkey)
218 RegCloseKey(hkey);
219 if (xhfpukey)
220 RegCloseKey(xhfpukey);
221 if (fpukey)
222 RegCloseKey(fpukey);
223
224}
225
226
227/***********************************************************************
228 * IsProcessorFeaturePresent [KERNELL32.880]
229 * RETURNS:
230 * TRUE if processorfeature present
231 * FALSE otherwise
232 */
233BOOL WINAPI IsProcessorFeaturePresent (DWORD feature) /* [in] feature number, see PF_ defines */
234{
235 SYSTEM_INFO si;
236 GetSystemInfo (&si); /* To ensure the information is loaded and cached */
237
238 if (feature < 64) {
239 dprintf(("IsProcessorFeaturePresent %x -> %x", feature, PF[feature]));
240 return PF[feature];
241 }
242 else
243 return FALSE;
244}
245//******************************************************************************
246//******************************************************************************
Note: See TracBrowser for help on using the repository browser.