Line data Source code
1 0 : /*
2 :
3 : OOCPUInfo.m
4 :
5 : Oolite
6 : Copyright (C) 2004-2013 Giles C Williams and contributors
7 :
8 : This program is free software; you can redistribute it and/or
9 : modify it under the terms of the GNU General Public License
10 : as published by the Free Software Foundation; either version 2
11 : of the License, or (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program; if not, write to the Free Software
20 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
21 : MA 02110-1301, USA.
22 :
23 : */
24 :
25 : #import "OOCPUInfo.h"
26 : #include <stdlib.h>
27 :
28 : #if OOLITE_MAC_OS_X
29 : #include <sys/sysctl.h>
30 : #elif (OOLITE_LINUX || OOLITE_WINDOWS)
31 : // Workaround for clang/glibc incompatibility.
32 : #if !OOLITE_HAVE_CLANG
33 : #define __block __glibc_block
34 : #endif
35 : #include <unistd.h>
36 : #if !OOLITE_HAVE_CLANG
37 : #undef __block
38 : #endif
39 : #endif
40 :
41 :
42 : #if 0
43 : // Confirm settings
44 : #if OOLITE_BIG_ENDIAN
45 : #warning Big-endian.
46 : #endif
47 : #if OOLITE_LITTLE_ENDIAN
48 : #warning Little-endian.
49 : #endif
50 : #if OOLITE_NATIVE_64_BIT
51 : #warning 64-bit.
52 : #else
53 : #warning 32-bit.
54 : #endif
55 : #endif
56 :
57 :
58 0 : static BOOL sInited = NO;
59 :
60 :
61 0 : static NSUInteger sNumberOfCPUs = 0; // Yes, really 0.
62 :
63 :
64 0 : void OOCPUInfoInit(void)
65 : {
66 : if (sInited) return;
67 :
68 : // Verify correctness of endian macros
69 : uint8_t endianTag[4] = {0x12, 0x34, 0x56, 0x78};
70 :
71 : #if OOLITE_BIG_ENDIAN
72 : if (*(uint32_t*)endianTag != 0x12345678)
73 : {
74 : OOLog(@"cpuInfo.endianTest.failed", @"%@", @"OOLITE_BIG_ENDIAN is set, but the system is not big-endian -- aborting.");
75 : exit(EXIT_FAILURE);
76 : }
77 : #endif
78 :
79 : #if OOLITE_LITTLE_ENDIAN
80 : if (*(uint32_t*)endianTag != 0x78563412)
81 : {
82 : OOLog(@"cpuInfo.endianTest.failed", @"%@", @"OOLITE_LITTLE_ENDIAN is set, but the system is not little-endian -- aborting.");
83 : exit(EXIT_FAILURE);
84 : }
85 : #endif
86 :
87 : // Count processors
88 : #if OOLITE_MAC_OS_X
89 : sNumberOfCPUs = [[NSProcessInfo processInfo] processorCount];
90 : #elif OOLITE_WINDOWS
91 : SYSTEM_INFO sysInfo;
92 :
93 : GetSystemInfo(&sysInfo);
94 : sNumberOfCPUs = sysInfo.dwNumberOfProcessors;
95 : #elif defined _SC_NPROCESSORS_ONLN
96 : sNumberOfCPUs = sysconf(_SC_NPROCESSORS_ONLN);
97 : #else
98 : #warning Do not know how to find number of CPUs on this architecture.
99 : #endif // OS selection
100 :
101 : sInited = YES;
102 : }
103 :
104 :
105 0 : NSUInteger OOCPUCount(void)
106 : {
107 : if (!sInited) OOCPUInfoInit();
108 : return (sNumberOfCPUs != 0) ? sNumberOfCPUs : 1;
109 : }
110 :
111 :
112 : #if (OOLITE_WINDOWS || OOLITE_LINUX)
113 : #if OOLITE_LINUX
114 : #define OO_GNU_INLINE __attribute__((gnu_inline))
115 : #else
116 : #define OO_GNU_INLINE
117 : #endif
118 : /*
119 : Taken straight out of the x64 gcc's __cpuid because our 32-bit compiler does not define it
120 : */
121 : inline OO_GNU_INLINE void OOCPUID(int CPUInfo[4], int InfoType)
122 : {
123 : __asm__ __volatile__ (
124 : /* Fixes building on 32-bit systems where %EBX is used for the GOT pointer */
125 : #if (OOLITE_LINUX && !defined __LP64__)
126 : " pushl %%ebx\n"
127 : " cpuid\n"
128 : " mov %%ebx, %1\n"
129 : " popl %%ebx"
130 : : "=a" (CPUInfo [0]), "=r" (CPUInfo [1]), "=c" (CPUInfo [2]), "=d" (CPUInfo [3])
131 : #else
132 : "cpuid"
133 : : "=a" (CPUInfo [0]), "=b" (CPUInfo [1]), "=c" (CPUInfo [2]), "=d" (CPUInfo [3])
134 : #endif
135 : : "a" (InfoType));
136 : }
137 :
138 :
139 : NSString* OOCPUDescription(void)
140 : {
141 : // This code taken from https://stackoverflow.com/questions/850774
142 : int CPUInfo[4] = {-1};
143 : unsigned nExIds, i = 0;
144 : char CPUBrandString[0x40];
145 : // Get the information associated with each extended ID.
146 : OOCPUID(CPUInfo, 0x80000000);
147 : nExIds = CPUInfo[0];
148 : for (i=0x80000000; i<=nExIds; ++i)
149 : {
150 : OOCPUID(CPUInfo, i);
151 : // Interpret CPU brand string
152 : if (i == 0x80000002)
153 : memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
154 : else if (i == 0x80000003)
155 : memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
156 : else if (i == 0x80000004)
157 : memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
158 : }
159 : return [NSString stringWithCString:CPUBrandString];
160 : }
161 :
162 :
163 : OOMemoryStatus OOSystemMemoryStatus(void)
164 : {
165 : const unsigned int toMegabyte = 1024 * 1024;
166 :
167 : OOMemoryStatus systemMemoryStatus;
168 : memset(&systemMemoryStatus, 0, sizeof(systemMemoryStatus));
169 :
170 : #if OOLITE_WINDOWS
171 : MEMORYSTATUSEX memStatus;
172 : memStatus.dwLength = sizeof(memStatus);
173 : if(GlobalMemoryStatusEx(&memStatus))
174 : {
175 : // return memory size in MB
176 : systemMemoryStatus.ooPhysicalMemory = memStatus.ullTotalPhys / toMegabyte;
177 : systemMemoryStatus.ooAvailableMemory = memStatus.ullAvailPhys / toMegabyte;
178 : }
179 : #else
180 : struct sysinfo si;
181 : sysinfo(&si);
182 : systemMemoryStatus.ooPhysicalMemory = (unsigned long long)(si.totalram / toMegabyte);
183 : systemMemoryStatus.ooAvailableMemory = (unsigned long long)(si.freeram / toMegabyte);
184 : #endif
185 :
186 : return systemMemoryStatus;
187 : }
188 : #endif //(OOLITE_WINDOWS || OOLITE_LINUX)
189 :
190 :
191 : #if OOLITE_WINDOWS
192 : NSString* operatingSystemFullVersion(void)
193 : {
194 : OSVERSIONINFOW osver;
195 : char outUBRString[65] = "";
196 :
197 : osver.dwOSVersionInfoSize = sizeof(osver);
198 : GetVersionExW (&osver);
199 :
200 : // get the Update Build Revision from the Registry
201 : HKEY hKey;
202 : if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0, KEY_READ, &hKey) == ERROR_SUCCESS)
203 : {
204 : DWORD dwUBRSize = sizeof(DWORD);
205 : DWORD dwUBR = 0;
206 : if (RegQueryValueEx(hKey,"UBR", NULL, NULL, (BYTE*)&dwUBR, &dwUBRSize) == ERROR_SUCCESS)
207 : {
208 : char strUBR[64] = "";
209 : ltoa(dwUBR, strUBR, 10);
210 : strcpy(outUBRString, ".");
211 : strcat(outUBRString, strUBR);
212 : }
213 : }
214 :
215 : return [NSString stringWithFormat:@"%lu.%lu.%lu%s %S",
216 : osver.dwMajorVersion, osver.dwMinorVersion, osver.dwBuildNumber, outUBRString, (const WCHAR *)osver.szCSDVersion];
217 : }
218 :
219 : /*
220 : is64bitSystem: Detect operating system bitness. This function is based mainly on code by Mark S. Kolich, as
221 : seen in http://mark.koli.ch/2009/10/reliably-checking-os-bitness-32-or-64-bit-on-windows-with-a-tiny-c-app.html
222 : */
223 : BOOL is64BitSystem(void)
224 : {
225 : #if defined(_WIN64)
226 : // if we have been compiled as a 64-bit app and we are running, we are obviously on a 64-bit system
227 : return YES;
228 : #else
229 : BOOL is64Bit = NO;
230 :
231 : IW64PFP IW64P = (IW64PFP)GetProcAddress(GetModuleHandle("kernel32"), "IsWow64Process");
232 : if(IW64P != NULL)
233 : {
234 : IW64P(GetCurrentProcess(), &is64Bit);
235 : }
236 :
237 : return is64Bit;
238 : #endif
239 : }
240 : #endif // OOLITE_WINDOWS
|