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