Blender V2.61 - r43446

util_system.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright 2011, Blender Foundation.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 #include "util_system.h"
00020 #include "util_types.h"
00021 
00022 #ifdef _WIN32
00023 #if(!defined(FREE_WINDOWS))
00024 #include <intrin.h>
00025 #endif
00026 #include <windows.h>
00027 #elif defined(__APPLE__)
00028 #include <sys/sysctl.h>
00029 #include <sys/types.h>
00030 #else
00031 #include <unistd.h>
00032 #endif
00033 
00034 CCL_NAMESPACE_BEGIN
00035 
00036 int system_cpu_thread_count()
00037 {
00038     static uint count = 0;
00039 
00040     if(count > 0)
00041         return count;
00042 
00043 #ifdef _WIN32
00044     SYSTEM_INFO info;
00045     GetSystemInfo(&info);
00046     count = (uint)info.dwNumberOfProcessors;
00047 #elif defined(__APPLE__)
00048     size_t len = sizeof(count);
00049     int mib[2] = { CTL_HW, HW_NCPU };
00050     
00051     sysctl(mib, 2, &count, &len, NULL, 0);
00052 #else
00053     count = (uint)sysconf(_SC_NPROCESSORS_ONLN);
00054 #endif
00055 
00056     if(count < 1)
00057         count = 1;
00058 
00059     return count;
00060 }
00061 
00062 #if !defined(_WIN32) || defined(FREE_WINDOWS)
00063 static void __cpuid(int data[4], int selector)
00064 {
00065 #ifdef __x86_64__
00066     asm("cpuid" : "=a" (data[0]), "=b" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector));
00067 #else
00068 #ifdef __i386__
00069     asm("pushl %%ebx    \n\t"
00070         "cpuid          \n\t"
00071         "movl %%ebx, %1 \n\t"
00072         "popl %%ebx     \n\t" : "=a" (data[0]), "=r" (data[1]), "=c" (data[2]), "=d" (data[3]) : "a"(selector));
00073 #else
00074     data[0] = data[1] = data[2] = data[3] = 0;
00075 #endif
00076 #endif
00077 }
00078 #endif
00079 
00080 static void replace_string(string& haystack, const string& needle, const string& other)
00081 {
00082     size_t i;
00083 
00084     while((i = haystack.find(needle)) != string::npos)
00085         haystack.replace(i, needle.length(), other);
00086 }
00087 
00088 string system_cpu_brand_string()
00089 {
00090     char buf[48];
00091     int result[4];
00092 
00093     __cpuid(result, 0x80000000);
00094 
00095     if(result[0] >= (int)0x80000004) {
00096         __cpuid((int*)(buf+0), 0x80000002);
00097         __cpuid((int*)(buf+16), 0x80000003);
00098         __cpuid((int*)(buf+32), 0x80000004);
00099 
00100         string brand = buf;
00101 
00102         /* make it a bit more presentable */
00103         replace_string(brand, "(TM)", "");
00104         replace_string(brand, "(R)", "");
00105 
00106         size_t i;
00107         if((i = brand.find("  ")) != string::npos)
00108             brand = brand.substr(0, i);
00109 
00110         return brand;
00111     }
00112 
00113     return "Unknown CPU";
00114 }
00115 
00116 int system_cpu_bits()
00117 {
00118     return (sizeof(void*)*8);
00119 }
00120 
00121 #if defined(__x86_64__) || defined(_M_X64) || defined(i386) || defined(_M_IX86)
00122 
00123 struct CPUCapabilities {
00124     bool x64;
00125     bool mmx;
00126     bool sse;
00127     bool sse2;
00128     bool sse3;
00129     bool ssse3;
00130     bool sse41;
00131     bool sse42;
00132     bool sse4a;
00133     bool avx;
00134     bool xop;
00135     bool fma3;
00136     bool fma4;
00137 };
00138 
00139 bool system_cpu_support_optimized()
00140 {
00141     static CPUCapabilities caps;
00142     static bool caps_init = false;
00143 
00144     if(!caps_init) {
00145         int result[4], num; //, num_ex;
00146 
00147         memset(&caps, 0, sizeof(caps));
00148 
00149         __cpuid(result, 0);
00150         num = result[0];
00151 
00152         /*__cpuid(result, 0x80000000);
00153         num_ex = result[0];*/
00154 
00155         if(num >= 1){
00156             __cpuid(result, 0x00000001);
00157             caps.mmx = (result[3] & ((int)1 << 23)) != 0;
00158             caps.sse = (result[3] & ((int)1 << 25)) != 0;
00159             caps.sse2 = (result[3] & ((int)1 << 26)) != 0;
00160             caps.sse3 = (result[2] & ((int)1 <<  0)) != 0;
00161 
00162             caps.ssse3 = (result[2] & ((int)1 <<  9)) != 0;
00163             caps.sse41 = (result[2] & ((int)1 << 19)) != 0;
00164             caps.sse42 = (result[2] & ((int)1 << 20)) != 0;
00165 
00166             caps.avx = (result[2] & ((int)1 << 28)) != 0;
00167             caps.fma3 = (result[2] & ((int)1 << 12)) != 0;
00168         }
00169 
00170         /*if(num_ex >= 0x80000001){
00171             __cpuid(result, 0x80000001);
00172             caps.x64 = (result[3] & ((int)1 << 29)) != 0;
00173             caps.sse4a = (result[2] & ((int)1 <<  6)) != 0;
00174             caps.fma4 = (result[2] & ((int)1 << 16)) != 0;
00175             caps.xop = (result[2] & ((int)1 << 11)) != 0;
00176         }*/
00177 
00178         caps_init = true;
00179     }
00180 
00181     /* optimization flags use these */
00182     return caps.sse && caps.sse2 && caps.sse3;
00183 }
00184 
00185 #else
00186 
00187 bool system_cpu_support_optimized()
00188 {
00189     return false;
00190 }
00191 
00192 #endif
00193 
00194 CCL_NAMESPACE_END
00195