2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
22 #include "Temperature.h"
26 #if defined(TARGET_DARWIN)
27 #include <sys/types.h>
28 #include <sys/sysctl.h>
29 #ifdef TARGET_DARWIN_OSX
32 #include <mach-o/arch.h>
37 #if defined(TARGET_FREEBSD)
38 #include <sys/types.h>
39 #include <sys/sysctl.h>
40 #include <sys/resource.h>
43 #if defined(TARGET_LINUX) && defined(__ARM_NEON__) && !defined(TARGET_ANDROID)
47 #include <linux/auxvec.h>
48 #include <asm/hwcap.h>
51 #if defined(TARGET_ANDROID)
52 #include "android/activity/AndroidFeatures.h"
58 // Defines to help with calls to CPUID
59 #define CPUID_INFOTYPE_STANDARD 0x00000001
60 #define CPUID_INFOTYPE_EXTENDED 0x80000001
63 // Bitmasks for the values returned by a call to cpuid with eax=0x00000001
64 #define CPUID_00000001_ECX_SSE3 (1<<0)
65 #define CPUID_00000001_ECX_SSSE3 (1<<9)
66 #define CPUID_00000001_ECX_SSE4 (1<<19)
67 #define CPUID_00000001_ECX_SSE42 (1<<20)
69 #define CPUID_00000001_EDX_MMX (1<<23)
70 #define CPUID_00000001_EDX_SSE (1<<25)
71 #define CPUID_00000001_EDX_SSE2 (1<<26)
74 // Bitmasks for the values returned by a call to cpuid with eax=0x80000001
75 #define CPUID_80000001_EDX_MMX2 (1<<22)
76 #define CPUID_80000001_EDX_MMX (1<<23)
77 #define CPUID_80000001_EDX_3DNOWEXT (1<<30)
78 #define CPUID_80000001_EDX_3DNOW (1<<31)
81 // Help with the __cpuid intrinsic of MSVC
90 #include "settings/AdvancedSettings.h"
91 #include "utils/StringUtils.h"
96 #define MINIMUM_TIME_BETWEEN_READS 500
99 /* replacement gettimeofday implementation, copy from dvdnav_internal.h */
100 #include <sys/timeb.h>
101 static inline int _private_gettimeofday( struct timeval *tv, void *tz )
106 tv->tv_usec = t.millitm * 1000;
109 #define gettimeofday(TV, TZ) _private_gettimeofday((TV), (TZ))
112 CCPUInfo::CCPUInfo(void)
114 m_fProcStat = m_fProcTemperature = m_fCPUFreq = NULL;
115 m_lastUsedPercentage = 0;
118 #if defined(TARGET_DARWIN)
120 std::string cpuVendor;
122 // The number of cores.
123 if (sysctlbyname("hw.activecpu", &m_cpuCount, &len, NULL, 0) == -1)
128 const NXArchInfo *info = NXGetLocalArchInfo();
130 m_cpuModel = info->description;
132 // NXGetLocalArchInfo is ugly for intel so keep using this method
135 if (sysctlbyname("machdep.cpu.brand_string", &buffer, &len, NULL, 0) == 0)
140 if (sysctlbyname("machdep.cpu.vendor", &buffer, &len, NULL, 0) == 0)
147 if (sysctlbyname("machdep.cpu.features", &buffer, &len, NULL, 0) == 0)
149 char* needle = buffer;
154 tok = strtok_r(needle, " ", &save);
157 if (0 == strcmp(tok, "MMX"))
158 m_cpuFeatures |= CPU_FEATURE_MMX;
159 else if (0 == strcmp(tok, "MMXEXT"))
160 m_cpuFeatures |= CPU_FEATURE_MMX2;
161 else if (0 == strcmp(tok, "SSE"))
162 m_cpuFeatures |= CPU_FEATURE_SSE;
163 else if (0 == strcmp(tok, "SSE2"))
164 m_cpuFeatures |= CPU_FEATURE_SSE2;
165 else if (0 == strcmp(tok, "SSE3"))
166 m_cpuFeatures |= CPU_FEATURE_SSE3;
167 else if (0 == strcmp(tok, "SSSE3"))
168 m_cpuFeatures |= CPU_FEATURE_SSSE3;
169 else if (0 == strcmp(tok, "SSE4.1"))
170 m_cpuFeatures |= CPU_FEATURE_SSE4;
171 else if (0 == strcmp(tok, "SSE4.2"))
172 m_cpuFeatures |= CPU_FEATURE_SSE42;
173 tok = strtok_r(NULL, " ", &save);
178 // Go through each core.
179 for (int i=0; i<m_cpuCount; i++)
183 core.m_strModel = m_cpuModel;
184 core.m_strVendor = cpuVendor;
185 m_cores[core.m_id] = core;
188 #elif defined(TARGET_WINDOWS)
193 LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",0, KEY_READ, &hKey);
194 ret = RegQueryValueEx(hKey,"ProcessorNameString", NULL, NULL, (LPBYTE)rgValue, &dwSize);
196 m_cpuModel = rgValue;
198 m_cpuModel = "Unknown";
202 SYSTEM_INFO siSysInfo;
203 GetSystemInfo(&siSysInfo);
204 m_cpuCount = siSysInfo.dwNumberOfProcessors;
209 #elif defined(TARGET_FREEBSD)
214 len = sizeof(m_cpuCount);
215 if (sysctlbyname("hw.ncpu", &m_cpuCount, &len, NULL, 0) != 0)
218 len = sizeof(cpumodel);
219 if (sysctlbyname("hw.model", &cpumodel, &len, NULL, 0) != 0)
220 (void)strncpy(cpumodel, "Unknown", 8);
221 m_cpuModel = cpumodel;
223 for (i = 0; i < m_cpuCount; i++)
227 core.m_strModel = m_cpuModel;
228 m_cores[core.m_id] = core;
231 m_fProcStat = fopen("/proc/stat", "r");
232 m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THM0/temperature", "r");
233 if (m_fProcTemperature == NULL)
234 m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THRM/temperature", "r");
235 if (m_fProcTemperature == NULL)
236 m_fProcTemperature = fopen("/proc/acpi/thermal_zone/THR0/temperature", "r");
237 if (m_fProcTemperature == NULL)
238 m_fProcTemperature = fopen("/proc/acpi/thermal_zone/TZ0/temperature", "r");
239 // read from the new location of the temperature data on new kernels, 2.6.39, 3.0 etc
240 if (m_fProcTemperature == NULL)
241 m_fProcTemperature = fopen("/sys/class/hwmon/hwmon0/temp1_input", "r");
242 if (m_fProcTemperature == NULL)
243 m_fProcTemperature = fopen("/sys/class/thermal/thermal_zone0/temp", "r"); // On Raspberry PIs
245 m_fCPUFreq = fopen ("/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq", "r");
248 FILE* fCPUInfo = fopen("/proc/cpuinfo", "r");
255 while (fgets(buffer, sizeof(buffer), fCPUInfo))
257 if (strncmp(buffer, "processor", strlen("processor"))==0)
259 char *needle = strstr(buffer, ":");
263 core.m_id = atoi(needle+2);
265 m_cores[core.m_id] = core;
269 else if (strncmp(buffer, "vendor_id", strlen("vendor_id"))==0)
271 char *needle = strstr(buffer, ":");
272 if (needle && strlen(needle)>3)
275 m_cores[nCurrId].m_strVendor = needle;
276 m_cores[nCurrId].m_strVendor.Trim();
279 else if (strncmp(buffer, "Processor", strlen("Processor"))==0)
281 char *needle = strstr(buffer, ":");
282 if (needle && strlen(needle)>3)
286 m_cores[nCurrId].m_strModel = m_cpuModel;
287 m_cores[nCurrId].m_strModel.Trim();
290 else if (strncmp(buffer, "BogoMIPS", strlen("BogoMIPS"))==0)
292 char *needle = strstr(buffer, ":");
293 if (needle && strlen(needle)>3)
296 m_cpuBogoMips = needle;
297 m_cores[nCurrId].m_strBogoMips = m_cpuBogoMips;
298 m_cores[nCurrId].m_strBogoMips.Trim();
301 else if (strncmp(buffer, "Hardware", strlen("Hardware"))==0)
303 char *needle = strstr(buffer, ":");
304 if (needle && strlen(needle)>3)
307 m_cpuHardware = needle;
308 m_cores[nCurrId].m_strHardware = m_cpuHardware;
309 m_cores[nCurrId].m_strHardware.Trim();
312 else if (strncmp(buffer, "Revision", strlen("Revision"))==0)
314 char *needle = strstr(buffer, ":");
315 if (needle && strlen(needle)>3)
318 m_cpuRevision = needle;
319 m_cores[nCurrId].m_strRevision = m_cpuRevision;
320 m_cores[nCurrId].m_strRevision.Trim();
323 else if (strncmp(buffer, "Serial", strlen("Serial"))==0)
325 char *needle = strstr(buffer, ":");
326 if (needle && strlen(needle)>3)
329 m_cpuSerial = needle;
330 m_cores[nCurrId].m_strSerial = m_cpuSerial;
331 m_cores[nCurrId].m_strSerial.Trim();
334 else if (strncmp(buffer, "model name", strlen("model name"))==0)
336 char *needle = strstr(buffer, ":");
337 if (needle && strlen(needle)>3)
341 m_cores[nCurrId].m_strModel = m_cpuModel;
342 m_cores[nCurrId].m_strModel.Trim();
345 else if (strncmp(buffer, "flags", 5) == 0)
347 char* needle = strchr(buffer, ':');
353 tok = strtok_r(needle, " ", &save);
356 if (0 == strcmp(tok, "mmx"))
357 m_cpuFeatures |= CPU_FEATURE_MMX;
358 else if (0 == strcmp(tok, "mmxext"))
359 m_cpuFeatures |= CPU_FEATURE_MMX2;
360 else if (0 == strcmp(tok, "sse"))
361 m_cpuFeatures |= CPU_FEATURE_SSE;
362 else if (0 == strcmp(tok, "sse2"))
363 m_cpuFeatures |= CPU_FEATURE_SSE2;
364 else if (0 == strcmp(tok, "sse3"))
365 m_cpuFeatures |= CPU_FEATURE_SSE3;
366 else if (0 == strcmp(tok, "ssse3"))
367 m_cpuFeatures |= CPU_FEATURE_SSSE3;
368 else if (0 == strcmp(tok, "sse4_1"))
369 m_cpuFeatures |= CPU_FEATURE_SSE4;
370 else if (0 == strcmp(tok, "sse4_2"))
371 m_cpuFeatures |= CPU_FEATURE_SSE42;
372 else if (0 == strcmp(tok, "3dnow"))
373 m_cpuFeatures |= CPU_FEATURE_3DNOW;
374 else if (0 == strcmp(tok, "3dnowext"))
375 m_cpuFeatures |= CPU_FEATURE_3DNOWEXT;
376 tok = strtok_r(NULL, " ", &save);
386 m_cpuModel = "Unknown";
390 StringUtils::RemoveDuplicatedSpacesAndTabs(m_cpuModel);
392 /* Set some default for empty string variables */
393 if (m_cpuBogoMips.empty())
394 m_cpuBogoMips = "N/A";
395 if (m_cpuHardware.empty())
396 m_cpuHardware = "N/A";
397 if (m_cpuRevision.empty())
398 m_cpuRevision = "N/A";
399 if (m_cpuSerial.empty())
402 readProcStat(m_userTicks, m_niceTicks, m_systemTicks, m_idleTicks, m_ioTicks);
403 m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS);
407 // Set MMX2 when SSE is present as SSE is a superset of MMX2 and Intel doesn't set the MMX2 cap
408 if (m_cpuFeatures & CPU_FEATURE_SSE)
409 m_cpuFeatures |= CPU_FEATURE_MMX2;
412 m_cpuFeatures |= CPU_FEATURE_NEON;
416 CCPUInfo::~CCPUInfo()
418 if (m_fProcStat != NULL)
421 if (m_fProcTemperature != NULL)
422 fclose(m_fProcTemperature);
424 if (m_fCPUFreq != NULL)
428 int CCPUInfo::getUsedPercentage()
430 if (!m_nextUsedReadTime.IsTimePast())
431 return m_lastUsedPercentage;
433 unsigned long long userTicks;
434 unsigned long long niceTicks;
435 unsigned long long systemTicks;
436 unsigned long long idleTicks;
437 unsigned long long ioTicks;
439 if (!readProcStat(userTicks, niceTicks, systemTicks, idleTicks, ioTicks))
440 return m_lastUsedPercentage;
442 userTicks -= m_userTicks;
443 niceTicks -= m_niceTicks;
444 systemTicks -= m_systemTicks;
445 idleTicks -= m_idleTicks;
446 ioTicks -= m_ioTicks;
448 #ifdef TARGET_WINDOWS
449 if(userTicks + systemTicks == 0)
450 return m_lastUsedPercentage;
451 int result = (int) ((userTicks + systemTicks - idleTicks) * 100 / (userTicks + systemTicks));
453 if(userTicks + niceTicks + systemTicks + idleTicks + ioTicks == 0)
454 return m_lastUsedPercentage;
455 int result = (int) ((userTicks + niceTicks + systemTicks) * 100 / (userTicks + niceTicks + systemTicks + idleTicks + ioTicks));
458 m_userTicks += userTicks;
459 m_niceTicks += niceTicks;
460 m_systemTicks += systemTicks;
461 m_idleTicks += idleTicks;
462 m_ioTicks += ioTicks;
464 m_lastUsedPercentage = result;
465 m_nextUsedReadTime.Set(MINIMUM_TIME_BETWEEN_READS);
470 float CCPUInfo::getCPUFrequency()
472 // Get CPU frequency, scaled to MHz.
473 #if defined(TARGET_DARWIN)
475 size_t len = sizeof(hz);
476 if (sysctlbyname("hw.cpufrequency", &hz, &len, NULL, 0) == -1)
478 return hz / 1000000.0;
479 #elif defined TARGET_WINDOWS
482 DWORD dwSize=sizeof(dwMHz);
483 LONG ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",0, KEY_READ, &hKey);
484 ret = RegQueryValueEx(hKey,"~MHz", NULL, NULL, (LPBYTE)&dwMHz, &dwSize);
490 #elif defined(TARGET_FREEBSD)
492 size_t len = sizeof(hz);
493 if (sysctlbyname("dev.cpu.0.freq", &hz, &len, NULL, 0) != 0)
502 fscanf(m_fCPUFreq, "%d", &value);
504 return value / 1000.0;
508 bool CCPUInfo::getTemperature(CTemperature& temperature)
513 #if defined(TARGET_DARWIN_OSX)
514 value = SMCGetTemperature(SMC_KEY_CPU_TEMP);
519 CStdString cmd = g_advancedSettings.m_cpuTempCmd;
521 temperature.SetState(CTemperature::invalid);
523 if (cmd.IsEmpty() && m_fProcTemperature == NULL)
528 p = popen (cmd.c_str(), "r");
531 ret = fscanf(p, "%d %c", &value, &scale);
537 // procfs is deprecated in the linux kernel, we should move away from
538 // using it for temperature data. It doesn't seem that sysfs has a
539 // general enough interface to bother implementing ATM.
541 rewind(m_fProcTemperature);
542 fflush(m_fProcTemperature);
543 ret = fscanf(m_fProcTemperature, "temperature: %d %c", &value, &scale);
545 // read from the temperature file of the new kernels
548 ret = fscanf(m_fProcTemperature, "%d", &value);
549 value = value / 1000;
559 if (scale == 'C' || scale == 'c')
560 temperature = CTemperature::CreateFromCelsius(value);
561 else if (scale == 'F' || scale == 'f')
562 temperature = CTemperature::CreateFromFahrenheit(value);
569 bool CCPUInfo::HasCoreId(int nCoreId) const
571 map<int, CoreInfo>::const_iterator iter = m_cores.find(nCoreId);
572 if (iter != m_cores.end())
577 const CoreInfo &CCPUInfo::GetCoreInfo(int nCoreId)
579 map<int, CoreInfo>::iterator iter = m_cores.find(nCoreId);
580 if (iter != m_cores.end())
583 static CoreInfo dummy;
587 bool CCPUInfo::readProcStat(unsigned long long& user, unsigned long long& nice,
588 unsigned long long& system, unsigned long long& idle, unsigned long long& io)
591 #ifdef TARGET_WINDOWS
595 ULARGE_INTEGER ulTime;
596 unsigned long long coreUser, coreSystem, coreIdle;
597 GetSystemTimes( &idleTime, &kernelTime, &userTime );
598 ulTime.HighPart = userTime.dwHighDateTime;
599 ulTime.LowPart = userTime.dwLowDateTime;
600 user = coreUser = ulTime.QuadPart;
602 ulTime.HighPart = kernelTime.dwHighDateTime;
603 ulTime.LowPart = kernelTime.dwLowDateTime;
604 system = coreSystem = ulTime.QuadPart;
606 ulTime.HighPart = idleTime.dwHighDateTime;
607 ulTime.LowPart = idleTime.dwLowDateTime;
608 idle = coreIdle = ulTime.QuadPart;
612 coreUser -= m_cores[0].m_user;
613 coreSystem -= m_cores[0].m_system;
614 coreIdle -= m_cores[0].m_idle;
615 m_cores[0].m_fPct = ((double)(coreUser + coreSystem - coreIdle) * 100.0) / (double)(coreUser + coreSystem);
616 m_cores[0].m_user += coreUser;
617 m_cores[0].m_system += coreSystem;
618 m_cores[0].m_idle += coreIdle;
622 #elif defined(TARGET_FREEBSD)
627 len = sizeof(long) * 32 * CPUSTATES;
628 if (sysctlbyname("kern.cp_times", NULL, &len, NULL, 0) != 0)
630 cptimes = (long*)malloc(len);
633 if (sysctlbyname("kern.cp_times", cptimes, &len, NULL, 0) != 0)
643 for (i = 0; i < m_cpuCount; i++)
645 long coreUser, coreNice, coreSystem, coreIdle, coreIO;
648 coreUser = cptimes[i * CPUSTATES + CP_USER];
649 coreNice = cptimes[i * CPUSTATES + CP_NICE];
650 coreSystem = cptimes[i * CPUSTATES + CP_SYS];
651 coreIO = cptimes[i * CPUSTATES + CP_INTR];
652 coreIdle = cptimes[i * CPUSTATES + CP_IDLE];
654 map<int, CoreInfo>::iterator iter = m_cores.find(i);
655 if (iter != m_cores.end())
657 coreUser -= iter->second.m_user;
658 coreNice -= iter->second.m_nice;
659 coreSystem -= iter->second.m_system;
660 coreIdle -= iter->second.m_idle;
661 coreIO -= iter->second.m_io;
663 total = (double)(coreUser + coreNice + coreSystem + coreIdle + coreIO);
665 iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total;
667 iter->second.m_user += coreUser;
668 iter->second.m_nice += coreNice;
669 iter->second.m_system += coreSystem;
670 iter->second.m_idle += coreIdle;
671 iter->second.m_io += coreIO;
675 system += coreSystem;
682 if (m_fProcStat == NULL)
689 if (!fgets(buf, sizeof(buf), m_fProcStat))
692 int num = sscanf(buf, "cpu %llu %llu %llu %llu %llu %*s\n", &user, &nice, &system, &idle, &io);
696 while (fgets(buf, sizeof(buf), m_fProcStat) && num >= 4)
698 unsigned long long coreUser, coreNice, coreSystem, coreIdle, coreIO;
700 num = sscanf(buf, "cpu%d %llu %llu %llu %llu %llu %*s\n", &nCpu, &coreUser, &coreNice, &coreSystem, &coreIdle, &coreIO);
704 map<int, CoreInfo>::iterator iter = m_cores.find(nCpu);
705 if (num > 4 && iter != m_cores.end())
707 coreUser -= iter->second.m_user;
708 coreNice -= iter->second.m_nice;
709 coreSystem -= iter->second.m_system;
710 coreIdle -= iter->second.m_idle;
711 coreIO -= iter->second.m_io;
713 double total = (double)(coreUser + coreNice + coreSystem + coreIdle + coreIO);
715 iter->second.m_fPct = 0.0f;
717 iter->second.m_fPct = ((double)(coreUser + coreNice + coreSystem) * 100.0) / total;
719 iter->second.m_user += coreUser;
720 iter->second.m_nice += coreNice;
721 iter->second.m_system += coreSystem;
722 iter->second.m_idle += coreIdle;
723 iter->second.m_io += coreIO;
731 CStdString CCPUInfo::GetCoresUsageString() const
734 map<int, CoreInfo>::const_iterator iter = m_cores.begin();
735 while (iter != m_cores.end())
738 #ifdef TARGET_WINDOWS
739 // atm we get only the average over all cores
740 strCore = StringUtils::Format("CPU %d core(s) average: %3.1f%% ", m_cpuCount, iter->second.m_fPct);
742 strCore = StringUtils::Format("CPU%d: %3.1f%% ", iter->first, iter->second.m_fPct);
750 void CCPUInfo::ReadCPUFeatures()
752 #ifdef TARGET_WINDOWS
754 int CPUInfo[4]; // receives EAX, EBX, ECD and EDX in that order
757 int MaxStdInfoType = CPUInfo[0];
759 if (MaxStdInfoType >= CPUID_INFOTYPE_STANDARD)
761 __cpuid(CPUInfo, CPUID_INFOTYPE_STANDARD);
762 if (CPUInfo[CPUINFO_EDX] & CPUID_00000001_EDX_MMX)
763 m_cpuFeatures |= CPU_FEATURE_MMX;
764 if (CPUInfo[CPUINFO_EDX] & CPUID_00000001_EDX_SSE)
765 m_cpuFeatures |= CPU_FEATURE_SSE;
766 if (CPUInfo[CPUINFO_EDX] & CPUID_00000001_EDX_SSE2)
767 m_cpuFeatures |= CPU_FEATURE_SSE2;
768 if (CPUInfo[CPUINFO_ECX] & CPUID_00000001_ECX_SSE3)
769 m_cpuFeatures |= CPU_FEATURE_SSE3;
770 if (CPUInfo[CPUINFO_ECX] & CPUID_00000001_ECX_SSSE3)
771 m_cpuFeatures |= CPU_FEATURE_SSSE3;
772 if (CPUInfo[CPUINFO_ECX] & CPUID_00000001_ECX_SSE4)
773 m_cpuFeatures |= CPU_FEATURE_SSE4;
774 if (CPUInfo[CPUINFO_ECX] & CPUID_00000001_ECX_SSE42)
775 m_cpuFeatures |= CPU_FEATURE_SSE42;
778 __cpuid(CPUInfo, 0x80000000);
779 int MaxExtInfoType = CPUInfo[0];
781 if (MaxExtInfoType >= CPUID_INFOTYPE_EXTENDED)
783 __cpuid(CPUInfo, CPUID_INFOTYPE_EXTENDED);
785 if (CPUInfo[CPUINFO_EDX] & CPUID_80000001_EDX_MMX)
786 m_cpuFeatures |= CPU_FEATURE_MMX;
787 if (CPUInfo[CPUINFO_EDX] & CPUID_80000001_EDX_MMX2)
788 m_cpuFeatures |= CPU_FEATURE_MMX2;
789 if (CPUInfo[CPUINFO_EDX] & CPUID_80000001_EDX_3DNOW)
790 m_cpuFeatures |= CPU_FEATURE_3DNOW;
791 if (CPUInfo[CPUINFO_EDX] & CPUID_80000001_EDX_3DNOWEXT)
792 m_cpuFeatures |= CPU_FEATURE_3DNOWEXT;
795 #elif defined(TARGET_DARWIN)
797 m_cpuFeatures |= CPU_FEATURE_ALTIVEC;
798 #elif defined(TARGET_DARWIN_IOS)
801 char buffer[512] ={0};
803 if (sysctlbyname("machdep.cpu.features", &buffer, &len, NULL, 0) == 0)
806 if (strstr(buffer,"MMX"))
807 m_cpuFeatures |= CPU_FEATURE_MMX;
808 if (strstr(buffer,"SSE "))
809 m_cpuFeatures |= CPU_FEATURE_SSE;
810 if (strstr(buffer,"SSE2"))
811 m_cpuFeatures |= CPU_FEATURE_SSE2;
812 if (strstr(buffer,"SSE3 "))
813 m_cpuFeatures |= CPU_FEATURE_SSE3;
814 if (strstr(buffer,"SSSE3"))
815 m_cpuFeatures |= CPU_FEATURE_SSSE3;
816 if (strstr(buffer,"SSE4.1"))
817 m_cpuFeatures |= CPU_FEATURE_SSE4;
818 if (strstr(buffer,"SSE4.2"))
819 m_cpuFeatures |= CPU_FEATURE_SSE42;
820 if (strstr(buffer,"3DNOW "))
821 m_cpuFeatures |= CPU_FEATURE_3DNOW;
822 if (strstr(buffer,"3DNOWEXT"))
823 m_cpuFeatures |= CPU_FEATURE_3DNOWEXT;
826 m_cpuFeatures |= CPU_FEATURE_MMX;
829 // empty on purpose, the implementation is in the constructor
830 #elif !defined(__powerpc__) && !defined(__ppc__) && !defined(__arm__)
831 m_cpuFeatures |= CPU_FEATURE_MMX;
832 #elif defined(__powerpc__) || defined(__ppc__)
833 m_cpuFeatures |= CPU_FEATURE_ALTIVEC;
837 bool CCPUInfo::HasNeon()
839 static int has_neon = -1;
840 #if defined (TARGET_ANDROID)
842 has_neon = (CAndroidFeatures::HasNeon()) ? 1 : 0;
844 #elif defined(TARGET_DARWIN_IOS)
847 #elif defined(TARGET_LINUX) && defined(__ARM_NEON__)
851 // why are we not looking at the Features in
852 // /proc/cpuinfo for neon ?
853 int fd = open("/proc/self/auxv", O_RDONLY);
857 while (read(fd, &auxv, sizeof(Elf32_auxv_t)) == sizeof(Elf32_auxv_t))
859 if (auxv.a_type == AT_HWCAP)
861 has_neon = (auxv.a_un.a_val & HWCAP_NEON) ? 1 : 0;
871 return has_neon == 1;
880 int r = c.getUsedPercentage();