diff options
33 files changed, 1196 insertions, 2467 deletions
| diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 3c689930b8..527ab42fc9 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -232,7 +232,6 @@ set(llcommon_HEADER_FILES      metaclasst.h      metaproperty.h      metapropertyt.h -    processor.h      reflective.h      reflectivet.h      roles_constants.h @@ -290,6 +289,7 @@ if (LL_TESTS)    LL_ADD_INTEGRATION_TEST(llframetimer "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llinstancetracker "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(lllazy "" "${test_libs}") +  LL_ADD_INTEGRATION_TEST(llprocessor "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llrand "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llsdserialize "" "${test_libs}")    LL_ADD_INTEGRATION_TEST(llstring "" "${test_libs}") diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index f39a4e6619..20727dd76e 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -238,7 +238,7 @@ U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  #else // windows or x86-mac or x86-linux or x86-solaris  U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  { -	static U64 sCPUClockFrequency = U64(CProcessor().GetCPUFrequency(50)); +	static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency());  	// we drop the low-order byte in our timers, so report a lower frequency  	return sCPUClockFrequency >> 8; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index f6ab55a6b5..98c9eabcd6 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -30,139 +30,385 @@   * $/LicenseInfo$   */ -// Filename: Processor.cpp -// ======================= -// Author: Benjamin Jurke -// File history: 27.02.2002  - File created. Support for Intel and AMD processors -//               05.03.2002  - Fixed the CPUID bug: On Pre-Pentium CPUs the CPUID -//                             command is not available -//                           - The CProcessor::WriteInfoTextFile function do not  -//                             longer use Win32 file functions (-> os independend) -//                           - Optional include of the windows.h header which is -//                             still need for CProcessor::GetCPUFrequency. -//               06.03.2002  - My birthday (18th :-)) -//                           - Replaced the '\r\n' line endings in function  -//                             CProcessor::CPUInfoToText by '\n' -//                           - Replaced unsigned __int64 by signed __int64 for -//                             solving some compiler conversion problems -//                           - Fixed a bug at family=6, model=6 (Celeron -> P2) -////////////////////////////////////////////////////////////////////////////////// -  #include "linden_common.h" +#include "llprocessor.h" -#include "processor.h" +#include "llerror.h" -#include <memory> +//#include <memory>  #if LL_WINDOWS  #	define WIN32_LEAN_AND_MEAN  #	include <winsock2.h>  #	include <windows.h> +#   include <intrin.h>  #endif -#if LL_LINUX -#include "llsys.h" -#endif // LL_LINUX +#include "llsd.h" + +#if LL_MSVC && _M_X64 +#      define LL_X86_64 1 +#      define LL_X86 1 +#elif LL_MSVC && _M_IX86 +#      define LL_X86 1 +#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) +#      define LL_X86_64 1 +#      define LL_X86 1 +#elif LL_GNUC && ( defined(__i386__) ) +#      define LL_X86 1 +#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) +#      define LL_PPC 1 +#endif + +class LLProcessorInfoImpl; // foward declaration for the mImpl; + +namespace  +{ +	enum cpu_info +	{ +		eBrandName = 0, +		eFrequency, +		eVendor, +		eStepping, +		eFamily, +		eExtendedFamily, +		eModel, +		eExtendedModel, +		eType, +		eBrandID, +		eFamilyName +	}; +		 + +	const char* cpu_info_names[] =  +	{ +		"Processor Name", +		"Frequency", +		"Vendor", +		"Stepping", +		"Family", +		"Extended Family", +		"Model", +		"Extended Model", +		"Type", +		"Brand ID", +		"Family Name" +	}; + +	enum cpu_config +	{ +		eMaxID, +		eMaxExtID, +		eCLFLUSHCacheLineSize, +		eAPICPhysicalID, +		eCacheLineSize, +		eL2Associativity, +		eCacheSizeK, +		eFeatureBits, +		eExtFeatureBits +	}; + +	const char* cpu_config_names[] = +	{ +		"Max Supported CPUID level", +		"Max Supported Ext. CPUID level", +		"CLFLUSH cache line size", +		"APIC Physical ID", +		"Cache Line Size",  +		"L2 Associativity", +		"Cache Size", +		"Feature Bits", +		"Ext. Feature Bits" +	}; -#if !LL_DARWIN && !LL_SOLARIS -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -// We need the QueryPerformanceCounter and Sleep functions -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE  -#endif +	// *NOTE:Mani - this contains the elements we reference directly and extensions beyond the first 32. +	// The rest of the names are referenced by bit maks returned from cpuid. +	enum cpu_features  +	{ +		eSSE_Ext=25, +		eSSE2_Ext=26, + +		eSSE3_Features=32, +		eMONTIOR_MWAIT=33, +		eCPLDebugStore=34, +		eThermalMonitor2=35, +		eAltivec=36 +	}; -// Some macros we often need -//////////////////////////// -#define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false) +	const char* cpu_feature_names[] = +	{ +		"x87 FPU On Chip", +		"Virtual-8086 Mode Enhancement", +		"Debugging Extensions", +		"Page Size Extensions", +		"Time Stamp Counter", +		"RDMSR and WRMSR Support", +		"Physical Address Extensions", +		"Machine Check Exception", +		"CMPXCHG8B Instruction", +		"APIC On Chip", +		"Unknown1", +		"SYSENTER and SYSEXIT", +		"Memory Type Range Registers", +		"PTE Global Bit", +		"Machine Check Architecture", +		"Conditional Move/Compare Instruction", +		"Page Attribute Table", +		"Page Size Extension", +		"Processor Serial Number", +		"CFLUSH Extension", +		"Unknown2", +		"Debug Store", +		"Thermal Monitor and Clock Ctrl", +		"MMX Technology", +		"FXSAVE/FXRSTOR", +		"SSE Extensions", +		"SSE2 Extensions", +		"Self Snoop", +		"Hyper-threading Technology", +		"Thermal Monitor", +		"Unknown4", +		"Pend. Brk. EN.", // 31 End of FeatureInfo bits + +		"SSE3 New Instructions", // 32 +		"MONITOR/MWAIT",  +		"CPL Qualified Debug Store", +		"Thermal Monitor 2", + +		"Altivec" +	}; + +	std::string intel_CPUFamilyName(int composed_family)  +	{ +		switch(composed_family) +		{ +		case 3: return "Intel i386"; +		case 4: return "Intel i486"; +		case 5: return "Intel Pentium"; +		case 6: return "Intel Pentium Pro/2/3, Core"; +		case 7: return "Intel Itanium (IA-64)"; +		case 0xF: return "Intel Pentium 4"; +		case 0x10: return "Intel Itanium 2 (IA-64)"; +		} +		return "Unknown"; +	} +	 +	std::string amd_CPUFamilyName(int composed_family)  +	{ +		switch(composed_family) +		{ +		case 4: return "AMD 80486/5x86"; +		case 5: return "AMD K5/K6"; +		case 6: return "AMD K7"; +		case 0xF: return "AMD K8"; +		case 0x10: return "AMD K8L"; +		} +   		return "Unknown"; +	} + +	std::string compute_CPUFamilyName(const char* cpu_vendor, int composed_family)  +	{ +		const char* intel_string = "GenuineIntel"; +		const char* amd_string = "AuthenticAMD"; +		if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) +		{ +			return intel_CPUFamilyName(composed_family); +		} +		else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) +		{ +			return amd_CPUFamilyName(composed_family); +		} +		return "Unknown"; +	} + +	std::string compute_CPUFamilyName(const char* cpu_vendor, int family, int ext_family)  +	{ +		const char* intel_string = "GenuineIntel"; +		const char* amd_string = "AuthenticAMD"; +		if(!strncmp(cpu_vendor, intel_string, strlen(intel_string))) +		{ +			U32 composed_family = family + ext_family; +			return intel_CPUFamilyName(composed_family); +		} +		else if(!strncmp(cpu_vendor, amd_string, strlen(amd_string))) +		{ +			U32 composed_family = (family == 0xF)  +				? family + ext_family +				: family; +			return amd_CPUFamilyName(composed_family); +		} +		return "Unknown"; +	} + +} // end unnamed namespace + +// The base class for implementations. +// Each platform should override this class. +class LLProcessorInfoImpl +{ +public: +	LLProcessorInfoImpl()  +	{ +		mProcessorInfo["info"] = LLSD::emptyMap(); +		mProcessorInfo["config"] = LLSD::emptyMap(); +		mProcessorInfo["extension"] = LLSD::emptyMap();		 +	} +	virtual ~LLProcessorInfoImpl() {} + +	F64 getCPUFrequency() const  +	{  +		return getInfo(eFrequency, 0).asReal();  +	} + +	bool hasSSE() const  +	{  +		return hasExtension(cpu_feature_names[eSSE_Ext]); +	} + +	bool hasSSE2() const +	{  +		return hasExtension(cpu_feature_names[eSSE2_Ext]); +	} + +	bool hasAltivec() const  +	{ +		return hasExtension("Altivec");  +	} + +	std::string getCPUFamilyName() const { return getInfo(eFamilyName, "Unknown").asString(); } +	std::string getCPUBrandName() const { return getInfo(eBrandName, "Unknown").asString(); } + +	// This is virtual to support a different linux format. +	// *NOTE:Mani - I didn't want to screw up server use of this data... +	virtual std::string getCPUFeatureDescription() const  +	{ +		std::ostringstream out; +		out << std::endl << std::endl; +		out << "// CPU General Information" << std::endl; +		out << "//////////////////////////" << std::endl; +		out << "Processor Name:   " << getCPUBrandName() << std::endl; +		out << "Frequency:        " << getCPUFrequency() << " MHz" << std::endl; +		out << "Vendor:			  " << getInfo(eVendor, "Unknown").asString() << std::endl; +		out << "Family:           " << getCPUFamilyName() << " (" << getInfo(eFamily, 0) << ")" << std::endl; +		out << "Extended family:  " << getInfo(eExtendedFamily, 0) << std::endl; +		out << "Model:            " << getInfo(eModel, 0) << std::endl; +		out << "Extended model:   " << getInfo(eExtendedModel, 0) << std::endl; +		out << "Type:             " << getInfo(eType, 0) << std::endl; +		out << "Brand ID:         " << getInfo(eBrandID, 0) << std::endl; +		out << std::endl; +		out << "// CPU Configuration" << std::endl; +		out << "//////////////////////////" << std::endl; +		 +		// Iterate through the dictionary of configuration options. +		LLSD configs = mProcessorInfo["config"]; +		for(LLSD::map_const_iterator cfgItr = configs.beginMap(); cfgItr != configs.endMap(); ++cfgItr) +		{ +			out << cfgItr->first << " = " << cfgItr->second << std::endl; +		} +		out << std::endl; +		 +		out << "// CPU Extensions" << std::endl; +		out << "//////////////////////////" << std::endl; +		 +		for(LLSD::map_const_iterator itr = mProcessorInfo["extension"].beginMap(); itr != mProcessorInfo["extension"].endMap(); ++itr) +		{ +			out << "  " << itr->first << std::endl;			 +		} +		return out.str();  +	} + +protected: +	void setInfo(cpu_info info_type, const LLSD& value)  +	{ +		setInfo(cpu_info_names[info_type], value); +	} +    LLSD getInfo(cpu_info info_type, const LLSD& defaultVal) const +	{ +		return getInfo(cpu_info_names[info_type], defaultVal); +	} + +	void setConfig(cpu_config config_type, const LLSD& value)  +	{  +		setConfig(cpu_config_names[config_type], value); +	} +	LLSD getConfig(cpu_config config_type, const LLSD& defaultVal) const +	{  +		return getConfig(cpu_config_names[config_type], defaultVal); +	} + +	void setExtension(const std::string& name) { mProcessorInfo["extension"][name] = "true"; } +	bool hasExtension(const std::string& name) const +	{  +		return mProcessorInfo["extension"].has(name); +	} + +private: +	void setInfo(const std::string& name, const LLSD& value) { mProcessorInfo["info"][name]=value; } +	LLSD getInfo(const std::string& name, const LLSD& defaultVal) const +	{  +		if(mProcessorInfo["info"].has(name)) +		{ +			return mProcessorInfo["info"][name]; +		} +		return defaultVal; +	} +	void setConfig(const std::string& name, const LLSD& value) { mProcessorInfo["config"][name]=value; } +	LLSD getConfig(const std::string& name, const LLSD& defaultVal) const +	{  +		LLSD r = mProcessorInfo["config"].get(name); +		return r.isDefined() ? r : defaultVal; +	} + +private: + +	LLSD mProcessorInfo; +}; + + +#ifdef LL_MSVC +// LL_MSVC and not LLWINDOWS because some of the following code  +// uses the MSVC compiler intrinsics __cpuid() and __rdtsc(). -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE  // Delays for the specified amount of milliseconds -static	void	_Delay(unsigned int ms) +static void _Delay(unsigned int ms)  { -   LARGE_INTEGER	freq, c1, c2; -	__int64		x; +	LARGE_INTEGER freq, c1, c2; +	__int64 x; -   // Get High-Res Timer frequency +	// Get High-Res Timer frequency  	if (!QueryPerformanceFrequency(&freq))	  		return; -		 +  	// Convert ms to High-Res Timer value  	x = freq.QuadPart/1000*ms;		 -   // Get first snapshot of High-Res Timer value +	// Get first snapshot of High-Res Timer value  	QueryPerformanceCounter(&c1);		  	do  	{ -            // Get second snapshot -	    QueryPerformanceCounter(&c2);	 +		// Get second snapshot +		QueryPerformanceCounter(&c2);	  	}while(c2.QuadPart-c1.QuadPart < x);  	// Loop while (second-first < x)	  } -#endif - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ -	uqwFrequency = 0; -	strCPUName[0] = 0; -	memset(&CPUInfo, 0, sizeof(CPUInfo)); -} -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to measure the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) +static F64 calculate_cpu_frequency(U32 measure_msecs)  { -#if LL_LINUX -	// use the shinier LLCPUInfo interface -	return 1000000.0F * gSysCPU.getMHz(); -#endif - -#ifndef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -	return 0; -#else -	// If there are invalid measure time parameters, zero msecs for example, -	// we've to exit the function -	if (uiMeasureMSecs < 1) +	if(measure_msecs == 0)  	{ -		// If theres already a measured frequency available, we return it -        if (uqwFrequency > 0) -			return uqwFrequency; -		else -			return 0; -	} - -	// Now we check if the CPUID command is available -	if (!CheckCPUIDPresence())  		return 0; - -	// First we get the CPUID standard level 0x00000001 -	unsigned long reg; -	__asm -	{ -		mov eax, 1 -        cpuid -		mov reg, edx  	} -	// Then we check, if the RDTSC (Real Date Time Stamp Counter) is available. -	// This function is necessary for our measure process. -	if (!(reg & (1 << 4))) -		return 0; -  	// After that we declare some vars and check the frequency of the high  	// resolution timer for the measure process. -	// If there's no high-res timer, we exit. -	__int64 starttime, endtime, timedif, freq, start, end, dif; +	// If there"s no high-res timer, we exit. +	unsigned __int64 starttime, endtime, timedif, freq, start, end, dif;  	if (!QueryPerformanceFrequency((LARGE_INTEGER *) &freq)) +	{  		return 0; +	}  	// Now we can init the measure process. We set the process and thread priority  	// to the highest available level (Realtime priority). Also we focus the @@ -178,35 +424,27 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)  	SetThreadPriority(hThread, THREAD_PRIORITY_TIME_CRITICAL);  	SetProcessAffinityMask(hProcess, dwNewMask); -	// Now we call a CPUID to ensure, that all other prior called functions are -	// completed now (serialization) -	__asm cpuid +	//// Now we call a CPUID to ensure, that all other prior called functions are +	//// completed now (serialization) +	//__asm cpuid +	int cpu_info[4] = {-1}; +	__cpuid(cpu_info, 0);  	// We ask the high-res timer for the start time  	QueryPerformanceCounter((LARGE_INTEGER *) &starttime);  	// Then we get the current cpu clock and store it -	__asm  -	{ -		rdtsc -		mov dword ptr [start+4], edx -		mov dword ptr [start], eax -	} +	start = __rdtsc();  	// Now we wart for some msecs -	_Delay(uiMeasureMSecs); -//	Sleep(uiMeasureMSecs); +	_Delay(measure_msecs); +	//	Sleep(uiMeasureMSecs);  	// We ask for the end time  	QueryPerformanceCounter((LARGE_INTEGER *) &endtime);  	// And also for the end cpu clock -	__asm  -	{ -		rdtsc -		mov dword ptr [end+4], edx -		mov dword ptr [end], eax -	} +	end = __rdtsc();  	// Now we can restore the default process and thread priorities  	SetProcessAffinityMask(hProcess, dwProcessMask); @@ -219,2075 +457,433 @@ F64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs)  	// And finally the frequency is the clock difference divided by the time  	// difference.  -	uqwFrequency = (F64)dif / (((F64)timedif) / freq); +	F64 frequency = (F64)dif / (((F64)timedif) / freq);  	// At last we just return the frequency that is also stored in the call -	// member var uqwFrequency -	return uqwFrequency; -#endif +	// member var uqwFrequency - converted to MHz +	return frequency  / (F64)1000000;  } -// bool CProcessor::AnalyzeIntelProcessor() -// ======================================== -// Private class function for analyzing an Intel processor -////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeIntelProcessor() +// Windows implementation +class LLProcessorInfoWindowsImpl : public LLProcessorInfoImpl  { -#if LL_WINDOWS -	unsigned long eaxreg, ebxreg, edxreg; - -	// First we check if the CPUID command is available -	if (!CheckCPUIDPresence()) -		return false; - -	// Now we get the CPUID standard level 0x00000001 -	__asm +public: +	LLProcessorInfoWindowsImpl()  	{ -		mov eax, 1 -		cpuid -		mov eaxreg, eax -		mov ebxreg, ebx -		mov edxreg, edx +		getCPUIDInfo(); +		setInfo(eFrequency, calculate_cpu_frequency(50));  	} -     -	// Then get the cpu model, family, type, stepping and brand id by masking -	// the eax and ebx register -	CPUInfo.uiStepping = eaxreg & 0xF; -	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF; -	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF; -	CPUInfo.uiType     = (eaxreg >> 12) & 0x3; -	CPUInfo.uiBrandID  = ebxreg & 0xF; - -	static const char* INTEL_BRAND[] = -	{ -		/* 0x00 */ "", -		/* 0x01 */ "0.18 micron Intel Celeron", -		/* 0x02 */ "0.18 micron Intel Pentium III", -		/* 0x03 */ "0.13 micron Intel Celeron", -		/* 0x04 */ "0.13 micron Intel Pentium III", -		/* 0x05 */ "", -		/* 0x06 */ "0.13 micron Intel Pentium III Mobile", -		/* 0x07 */ "0.13 micron Intel Celeron Mobile", -		/* 0x08 */ "0.18 micron Intel Pentium 4", -		/* 0x09 */ "0.13 micron Intel Pentium 4", -		/* 0x0A */ "0.13 micron Intel Celeron", -		/* 0x0B */ "0.13 micron Intel Pentium 4 Xeon", -		/* 0x0C */ "Intel Xeon MP", -		/* 0x0D */ "", -		/* 0x0E */ "0.18 micron Intel Pentium 4 Xeon", -		/* 0x0F */ "Mobile Intel Celeron", -		/* 0x10 */ "", -		/* 0x11 */ "Mobile Genuine Intel", -		/* 0x12 */ "Intel Celeron M", -		/* 0x13 */ "Mobile Intel Celeron", -		/* 0x14 */ "Intel Celeron", -		/* 0x15 */ "Mobile Genuine Intel", -		/* 0x16 */ "Intel Pentium M", -		/* 0x17 */ "Mobile Intel Celeron", -	}; -	// Only override the brand if we have it in the lookup table.  We should -	// already have a string here from GetCPUInfo().  JC -	if ( CPUInfo.uiBrandID < LL_ARRAY_SIZE(INTEL_BRAND) ) +private: +	void getCPUIDInfo()  	{ -		strncpy(CPUInfo.strBrandID, INTEL_BRAND[CPUInfo.uiBrandID], sizeof(CPUInfo.strBrandID)-1); -		CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; +		// http://msdn.microsoft.com/en-us/library/hskdteyh(VS.80).aspx + +		// __cpuid with an InfoType argument of 0 returns the number of +		// valid Ids in cpu_info[0] and the CPU identification string in +		// the other three array elements. The CPU identification string is +		// not in linear order. The code below arranges the information  +		// in a human readable form. +		int cpu_info[4] = {-1}; +		__cpuid(cpu_info, 0); +		unsigned int ids = (unsigned int)cpu_info[0]; +		setConfig(eMaxID, (S32)ids); + +		char cpu_vendor[0x20]; +		memset(cpu_vendor, 0, sizeof(cpu_vendor)); +		*((int*)cpu_vendor) = cpu_info[1]; +		*((int*)(cpu_vendor+4)) = cpu_info[3]; +		*((int*)(cpu_vendor+8)) = cpu_info[2]; +		setInfo(eVendor, cpu_vendor); -		if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) +		// Get the information associated with each valid Id +		for(unsigned int i=0; i<=ids; ++i)  		{ -			strcpy(CPUInfo.strBrandID, "0.18 micron Intel Pentium III Xeon"); -		} -	} +			__cpuid(cpu_info, i); -	// Then we translate the cpu family -    switch (CPUInfo.uiFamily) -	{ -		case 3:			// Family = 3:  i386 (80386) processor family -			strcpy(CPUInfo.strFamily, "Intel i386");	/* Flawfinder: ignore */	 -			break; -		case 4:			// Family = 4:  i486 (80486) processor family -			strcpy(CPUInfo.strFamily, "Intel i486");	/* Flawfinder: ignore */	 -			break; -		case 5:			// Family = 5:  Pentium (80586) processor family -			strcpy(CPUInfo.strFamily, "Intel Pentium");	/* Flawfinder: ignore */	 -			break; -		case 6:			// Family = 6:  Pentium Pro (80686) processor family -			strcpy(CPUInfo.strFamily, "Intel Pentium Pro/2/3, Core");	/* Flawfinder: ignore */	 -			break; -		case 15:		// Family = 15:  Extended family specific -			// Masking the extended family -			CPUInfo.uiExtendedFamily = (eaxreg >> 20) & 0xFF; -			switch (CPUInfo.uiExtendedFamily) -			{ -				case 0:			// Family = 15, Ext. Family = 0:  Pentium 4 (80786 ??) processor family -					strcpy(CPUInfo.strFamily, "Intel Pentium 4");	/* Flawfinder: ignore */	 -					break; -				case 1:			// Family = 15, Ext. Family = 1:  McKinley (64-bit) processor family -					strcpy(CPUInfo.strFamily, "Intel McKinley (IA-64)");	/* Flawfinder: ignore */	 -					break; -				default:		// Sure is sure -					strcpy(CPUInfo.strFamily, "Unknown Intel Pentium 4+");	/* Flawfinder: ignore */	 -					break; -			} -			break; -		default:		// Failsave -			strcpy(CPUInfo.strFamily, "Unknown");	/* Flawfinder: ignore */ -			break; -    } - -	// Now we come to the big deal, the exact model name -	switch (CPUInfo.uiFamily) -	{ -		case 3:			// i386 (80386) processor family -			strcpy(CPUInfo.strModel, "Unknown Intel i386");	/* Flawfinder: ignore */ -			strncat(strCPUName, "Intel i386", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		 -			break; -		case 4:			// i486 (80486) processor family -			switch (CPUInfo.uiModel) -			{ -				case 0:			// Model = 0:  i486 DX-25/33 processor model -					strcpy(CPUInfo.strModel, "Intel i486 DX-25/33");	/* Flawfinder: ignore */			 -					strncat(strCPUName, "Intel i486 DX-25/33", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		 -					break; -				case 1:			// Model = 1:  i486 DX-50 processor model -					strcpy(CPUInfo.strModel, "Intel i486 DX-50");	/* Flawfinder: ignore */		 -					strncat(strCPUName, "Intel i486 DX-50", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		 -					break; -				case 2:			// Model = 2:  i486 SX processor model -					strcpy(CPUInfo.strModel, "Intel i486 SX");	/* Flawfinder: ignore */		 -					strncat(strCPUName, "Intel i486 SX", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		 -					break; -				case 3:			// Model = 3:  i486 DX2 (with i487 numeric coprocessor) processor model -					strcpy(CPUInfo.strModel, "Intel i486 487/DX2");	/* Flawfinder: ignore */		 -					strncat(strCPUName, "Intel i486 DX2 with i487 numeric coprocessor", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */		 -					break; -				case 4:			// Model = 4:  i486 SL processor model (never heard ?!?) -					strcpy(CPUInfo.strModel, "Intel i486 SL");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 SL", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 5:			// Model = 5:  i486 SX2 processor model -					strcpy(CPUInfo.strModel, "Intel i486 SX2");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 SX2", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 7:			// Model = 7:  i486 write-back enhanced DX2 processor model -					strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX2");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 write-back enhanced DX2", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 8:			// Model = 8:  i486 DX4 processor model -					strcpy(CPUInfo.strModel, "Intel i486 DX4");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 9:			// Model = 9:  i486 write-back enhanced DX4 processor model -					strcpy(CPUInfo.strModel, "Intel i486 write-back enhanced DX4");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 DX4", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				default:		// ... -					strcpy(CPUInfo.strModel, "Unknown Intel i486");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel i486 (Unknown model)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -			} -			break; -		case 5:			// Pentium (80586) processor family -			switch (CPUInfo.uiModel) -			{ -				case 0:			// Model = 0:  Pentium (P5 A-Step) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium (P5 A-Step)");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel Pentium (P5 A-Step core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break;		// Famous for the DIV bug, as far as I know -				case 1:			// Model = 1:  Pentium 60/66 processor model -					strcpy(CPUInfo.strModel, "Intel Pentium 60/66 (P5)");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel Pentium 60/66 (P5 core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 2:			// Model = 2:  Pentium 75-200 (P54C) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium 75-200 (P54C)");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel Pentium 75-200 (P54C core)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -					break; -				case 3:			// Model = 3:  Pentium overdrive for 486 systems processor model -					strcpy(CPUInfo.strModel, "Intel Pentium for 486 system (P24T Overdrive)");	/* Flawfinder: ignore */	 -					strncat(strCPUName, "Intel Pentium for 486 (P24T overdrive core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 4:			// Model = 4:  Pentium MMX processor model -					strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C)");	/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium MMX (P55C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 7:			// Model = 7:  Pentium processor model (don't know difference to Model=2) -					strcpy(CPUInfo.strModel, "Intel Pentium (P54C)");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium (P54C core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 8:			// Model = 8:  Pentium MMX (0.25 micron) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium MMX (P55C), 0.25 micron");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium MMX (P55C core), 0.25 micron", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				default:		// ... -					strcpy(CPUInfo.strModel, "Unknown Intel Pentium");	/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium (Unknown P5-model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -			} -			break; -		case 6:			// Pentium Pro (80686) processor family -			switch (CPUInfo.uiModel) -			{ -				case 0:			// Model = 0:  Pentium Pro (P6 A-Step) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6 A-Step)");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium Pro (P6 A-Step core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 1:			// Model = 1:  Pentium Pro -					strcpy(CPUInfo.strModel, "Intel Pentium Pro (P6)");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium Pro (P6 core)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 3:			// Model = 3:  Pentium II (66 MHz FSB, I think) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium II Model 3, 0.28 micron");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium II (Model 3 core, 0.28 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 5:			// Model = 5:  Pentium II/Xeon/Celeron (0.25 micron) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium II Model 5/Xeon/Celeron, 0.25 micron");		/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium II/Xeon/Celeron (Model 5 core, 0.25 micron process)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 6:			// Model = 6:  Pentium II with internal L2 cache -					strcpy(CPUInfo.strModel, "Intel Pentium II - internal L2 cache");	/*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium II with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 7:			// Model = 7:  Pentium III/Xeon (extern L2 cache) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium III/Pentium III Xeon - external L2 cache, 0.25 micron");		 /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium III/Pentium III Xeon (0.25 micron process) with external L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 8:			// Model = 8:  Pentium III/Xeon/Celeron (256 KB on-die L2 cache) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");	 /*Flawfinder: ignore*/ -					// We want to know it exactly: -					switch (CPUInfo.uiBrandID) -					{ -						case 1:			// Model = 8, Brand id = 1:  Celeron (on-die L2 cache) processor model -							strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -                        case 2:			// Model = 8, Brand id = 2:  Pentium III (on-die L2 cache) processor model (my current cpu :-)) -							strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						case 3:			// Model = 8, Brand id = 3:  Pentium III Xeon (on-die L2 cache) processor model -                            strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						default:		// ... -							strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -					} -					break; -				case 9:		// Model = 9:  Intel Pentium M processor, Intel Celeron M processor, model 9 -					strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");	 /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 0xA:		// Model = 0xA:  Pentium III/Xeon/Celeron (1 or 2 MB on-die L2 cache) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.18 micron");	 /*Flawfinder: ignore*/ -					// Exact detection: -					switch (CPUInfo.uiBrandID) -					{ -						case 1:			// Model = 0xA, Brand id = 1:  Celeron (1 or 2 MB on-die L2 cache (does it exist??)) processor model -							strncat(strCPUName, "Intel Celeron (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -                        case 2:			// Model = 0xA, Brand id = 2:  Pentium III (1 or 2 MB on-die L2 cache (never seen...)) processor model -							strncat(strCPUName, "Intel Pentium III (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						case 3:			// Model = 0xA, Brand id = 3:  Pentium III Xeon (1 or 2 MB on-die L2 cache) processor model -                            strncat(strCPUName, "Intel Pentium III Xeon (0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						default:		// Getting bored of this............ -							strncat(strCPUName, "Intel Pentium III core (unknown model, 0.18 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -					} -					break; -				case 0xB:		// Model = 0xB: Pentium III/Xeon/Celeron (Tualatin core, on-die cache) processor model -					strcpy(CPUInfo.strModel, "Intel Pentium III/Celeron/Pentium III Xeon - internal L2 cache, 0.13 micron");	 /*Flawfinder: ignore*/ -					// Omniscient: ;-) -					switch (CPUInfo.uiBrandID) -					{ -						case 3:			// Model = 0xB, Brand id = 3:  Celeron (Tualatin core) processor model -							strncat(strCPUName, "Intel Celeron (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -                        case 4:			// Model = 0xB, Brand id = 4:  Pentium III (Tualatin core) processor model -							strncat(strCPUName, "Intel Pentium III (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						case 7:			// Model = 0xB, Brand id = 7:  Celeron mobile (Tualatin core) processor model -                            strncat(strCPUName, "Intel Celeron mobile (Tualatin core, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -						default:		// *bored* -							strncat(strCPUName, "Intel Pentium III Tualatin core (unknown model, 0.13 micron process) with internal L2 cache", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -							break; -					} -					break; -				case 0xD:		// Model = 0xD:  Intel Pentium M processor, Intel Celeron M processor, model D -					strcpy(CPUInfo.strModel, "Intel Pentium M Series Processor");	 /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium M Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -				case 0xE:		// Model = 0xE:  Intel Core Duo processor, Intel Core Solo processor, model E -					strcpy(CPUInfo.strModel, "Intel Core Series Processor");	 /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Core Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break;	 -				case 0xF:		// Model = 0xF:  Intel Core 2 Duo processor, model F -					strcpy(CPUInfo.strModel, "Intel Core 2 Series Processor");	 /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Core 2 Series Processor", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break;	 -				default:		// *more bored* -					strcpy(CPUInfo.strModel, "Unknown Intel Pentium Pro/2/3, Core"); /*Flawfinder: ignore*/ -					strncat(strCPUName, "Intel Pentium Pro/2/3, Core (Unknown model)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					break; -			} -			break; -		case 15:		// Extended processor family -			// Masking the extended model -			CPUInfo.uiExtendedModel = (eaxreg >> 16) & 0xFF; -			switch (CPUInfo.uiModel) +			// Interpret CPU feature information. +			if  (i == 1)  			{ -				case 0:			// Model = 0:  Pentium 4 Willamette (A-Step) core -					if ((CPUInfo.uiBrandID) == 8)	// Brand id = 8:  P4 Willamette -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette (A-Step)"); /*Flawfinder: ignore*/ -						strncat(strCPUName, "Intel Pentium 4 Willamette (A-Step)", sizeof(strCPUName)-(strlen(strCPUName)-1)); /*Flawfinder: ignore*/ -					} -					else							// else Xeon -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon (A-Step)");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Willamette Xeon (A-Step)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */	 -					} -					break; -				case 1:			// Model = 1:  Pentium 4 Willamette core -					if ((CPUInfo.uiBrandID) == 8)	// Brand id = 8:  P4 Willamette +				setInfo(eStepping, cpu_info[0] & 0xf); +				setInfo(eModel, (cpu_info[0] >> 4) & 0xf); +				int family = (cpu_info[0] >> 8) & 0xf; +				setInfo(eFamily, family); +				setInfo(eType, (cpu_info[0] >> 12) & 0x3); +				setInfo(eExtendedModel, (cpu_info[0] >> 16) & 0xf); +				int ext_family = (cpu_info[0] >> 20) & 0xff; +				setInfo(eExtendedFamily, ext_family); +				setInfo(eBrandID, cpu_info[1] & 0xff); + +				setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); + +				setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); +				setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); +				 +				if(cpu_info[2] & 0x1) +				{ +					setExtension(cpu_feature_names[eSSE3_Features]); +				} + +				if(cpu_info[2] & 0x8) +				{ +					setExtension(cpu_feature_names[eMONTIOR_MWAIT]); +				} +				 +				if(cpu_info[2] & 0x10) +				{ +					setExtension(cpu_feature_names[eCPLDebugStore]); +				} +				 +				if(cpu_info[2] & 0x100) +				{ +					setExtension(cpu_feature_names[eThermalMonitor2]); +				} +						 +				unsigned int feature_info = (unsigned int) cpu_info[3]; +				for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1) +				{ +					if(feature_info & bit)  					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ +						setExtension(cpu_feature_names[index]);  					} -					else							// else Xeon -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette Xeon");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -					} -					break; -				case 2:			// Model = 2:  Pentium 4 Northwood core -					if (((CPUInfo.uiBrandID) == 9) || ((CPUInfo.uiBrandID) == 0xA))		// P4 Willamette -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Northwood", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -					} -					else							// Xeon -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Northwood Xeon");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Northwood Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -					} -					break; -				default:		// Silly stupid never used failsave option -					strcpy(CPUInfo.strModel, "Unknown Intel Pentium 4");		/* Flawfinder: ignore */ -					strncat(strCPUName, "Intel Pentium 4 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -					break; +				}  			} -			break; -		default:		// *grmpf* -			strcpy(CPUInfo.strModel, "Unknown Intel model");		/* Flawfinder: ignore */ -			strncat(strCPUName, "Intel (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -			break; -    } - -	// After the long processor model block we now come to the processors serial -	// number. -	// First of all we check if the processor supports the serial number -	if (CPUInfo.MaxSupportedLevel >= 3) -	{ -		// If it supports the serial number CPUID level 0x00000003 we read the data -		unsigned long sig1, sig2, sig3; -		__asm -		{ -			mov eax, 1 -			cpuid -			mov sig1, eax -			mov eax, 3 -			cpuid -			mov sig2, ecx -			mov sig3, edx  		} -		// Then we convert the data to a readable string -		snprintf(	/* Flawfinder: ignore */ -			CPUInfo.strProcessorSerial, -			sizeof(CPUInfo.strProcessorSerial), -			"%04lX-%04lX-%04lX-%04lX-%04lX-%04lX", -			sig1 >> 16, -			sig1 & 0xFFFF, -			sig3 >> 16, -			sig3 & 0xFFFF, -			sig2 >> 16, sig2 & 0xFFFF); -	} -	else -	{ -		// If there's no serial number support we just put "No serial number" -		snprintf(	/* Flawfinder: ignore */ -			CPUInfo.strProcessorSerial, -			sizeof(CPUInfo.strProcessorSerial), -			"No Processor Serial Number");	 -	} - -	// Now we get the standard processor extensions -	GetStandardProcessorExtensions(); -	// And finally the processor configuration (caches, TLBs, ...) and translate -	// the data to readable strings -	GetStandardProcessorConfiguration(); -	TranslateProcessorConfiguration(); +		// Calling __cpuid with 0x80000000 as the InfoType argument +		// gets the number of valid extended IDs. +		__cpuid(cpu_info, 0x80000000); +		unsigned int ext_ids = cpu_info[0]; +		setConfig(eMaxExtID, 0); -	// At last... -	return true; -#else -	return FALSE; -#endif -} +		char cpu_brand_string[0x40]; +		memset(cpu_brand_string, 0, sizeof(cpu_brand_string)); -// bool CProcessor::AnalyzeAMDProcessor() -// ====================================== -// Private class function for analyzing an AMD processor -//////////////////////////////////////////////////////// -bool CProcessor::AnalyzeAMDProcessor() -{ -#if LL_WINDOWS -	unsigned long eaxreg, ebxreg, ecxreg, edxreg; - -	// First of all we check if the CPUID command is available -	if (!CheckCPUIDPresence()) -		return 0; - -	// Now we get the CPUID standard level 0x00000001 -	__asm -	{ -		mov eax, 1 -		cpuid -		mov eaxreg, eax -		mov ebxreg, ebx -		mov edxreg, edx -	} -     -	// Then we mask the model, family, stepping and type (AMD does not support brand id) -	CPUInfo.uiStepping = eaxreg & 0xF; -	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF; -	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF; -	CPUInfo.uiType     = (eaxreg >> 12) & 0x3; - -	// Now we check if the processor supports the brand id string extended CPUID level -	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000004) -	{ -		// If it supports the extended CPUID level 0x80000004 we read the data -		char tmp[52];		/* Flawfinder: ignore */ -		memset(tmp, 0, sizeof(tmp)); -        __asm +		// Get the information associated with each extended ID. +		for(unsigned int i=0x80000000; i<=ext_ids; ++i)  		{ -			mov eax, 0x80000002 -			cpuid -			mov dword ptr [tmp], eax -			mov dword ptr [tmp+4], ebx -			mov dword ptr [tmp+8], ecx -			mov dword ptr [tmp+12], edx -			mov eax, 0x80000003 -			cpuid -			mov dword ptr [tmp+16], eax -			mov dword ptr [tmp+20], ebx -			mov dword ptr [tmp+24], ecx -			mov dword ptr [tmp+28], edx -			mov eax, 0x80000004 -			cpuid -			mov dword ptr [tmp+32], eax -			mov dword ptr [tmp+36], ebx -			mov dword ptr [tmp+40], ecx -			mov dword ptr [tmp+44], edx -		} -		// And copy it to the brand id string -		strncpy(CPUInfo.strBrandID, tmp,sizeof(CPUInfo.strBrandID)-1); -		CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; -	} -	else -	{ -		// Or just tell there is no brand id string support -		strcpy(CPUInfo.strBrandID, "");		/* Flawfinder: ignore */ -	} - -	// After that we translate the processor family -    switch(CPUInfo.uiFamily) -	{ -		case 4:			// Family = 4:  486 (80486) or 5x86 (80486) processor family -			switch (CPUInfo.uiModel) +			__cpuid(cpu_info, i); + +			// Interpret CPU brand string and cache information. +			if  (i == 0x80000002) +				memcpy(cpu_brand_string, cpu_info, sizeof(cpu_info)); +			else if  (i == 0x80000003) +				memcpy(cpu_brand_string + 16, cpu_info, sizeof(cpu_info)); +			else if  (i == 0x80000004)  			{ -				case 3:			// Thanks to AMD for this nice form of family -				case 7:			// detection.... *grmpf* -				case 8: -				case 9: -					strcpy(CPUInfo.strFamily, "AMD 80486");		/* Flawfinder: ignore */ -					break; -				case 0xE: -				case 0xF: -					strcpy(CPUInfo.strFamily, "AMD 5x86");		/* Flawfinder: ignore */ -					break; -				default: -					strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */ -					break; +				memcpy(cpu_brand_string + 32, cpu_info, sizeof(cpu_info)); +				setInfo(eBrandName, cpu_brand_string);  			} -			break; -		case 5:			// Family = 5:  K5 or K6 processor family -			switch (CPUInfo.uiModel) +			else if  (i == 0x80000006)  			{ -				case 0: -				case 1: -				case 2: -				case 3: -					strcpy(CPUInfo.strFamily, "AMD K5");		/* Flawfinder: ignore */ -					break; -				case 6: -				case 7: -				case 8: -				case 9: -					strcpy(CPUInfo.strFamily, "AMD K6");		/* Flawfinder: ignore */ -					break; -				default: -					strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */ -					break; +				setConfig(eCacheLineSize, cpu_info[2] & 0xff); +				setConfig(eL2Associativity, (cpu_info[2] >> 12) & 0xf); +				setConfig(eCacheSizeK, (cpu_info[2] >> 16) & 0xffff);  			} -			break; -		case 6:			// Family = 6:  K7 (Athlon, ...) processor family -			strcpy(CPUInfo.strFamily, "AMD K7");		/* Flawfinder: ignore */ -			break; -		default:		// For security -			strcpy(CPUInfo.strFamily, "Unknown family");		/* Flawfinder: ignore */ -			break; +		}  	} +}; -	// After the family detection we come to the specific processor model -	// detection -	switch (CPUInfo.uiFamily) -	{ -		case 4:			// Family = 4:  486 (80486) or 5x85 (80486) processor family -			switch (CPUInfo.uiModel) -			{ -				case 3:			// Model = 3:  80486 DX2 -					strcpy(CPUInfo.strModel, "AMD 80486 DX2");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 80486 DX2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 7:			// Model = 7:  80486 write-back enhanced DX2 -					strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX2");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 80486 write-back enhanced DX2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 8:			// Model = 8:  80486 DX4 -					strcpy(CPUInfo.strModel, "AMD 80486 DX4");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 80486 DX4", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 9:			// Model = 9:  80486 write-back enhanced DX4 -					strcpy(CPUInfo.strModel, "AMD 80486 write-back enhanced DX4");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 80486 write-back enhanced DX4", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 0xE:		// Model = 0xE:  5x86 -					strcpy(CPUInfo.strModel, "AMD 5x86");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 5x86", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 0xF:		// Model = 0xF:  5x86 write-back enhanced (oh my god.....) -					strcpy(CPUInfo.strModel, "AMD 5x86 write-back enhanced");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 5x86 write-back enhanced", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				default:		// ... -					strcpy(CPUInfo.strModel, "Unknown AMD 80486 or 5x86 model");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD 80486 or 5x86 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -			} -			break; -		case 5:			// Family = 5:  K5 / K6 processor family -			switch (CPUInfo.uiModel) -			{ -				case 0:			// Model = 0:  K5 SSA 5 (Pentium Rating *ggg* 75, 90 and 100 MHz) -					strcpy(CPUInfo.strModel, "AMD K5 SSA5 (PR75, PR90, PR100)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K5 SSA5 (PR75, PR90, PR100)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 1:			// Model = 1:  K5 5k86 (PR 120 and 133 MHz) -					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR120, PR133)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K5 5k86 (PR120, PR133)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 2:			// Model = 2:  K5 5k86 (PR 166 MHz) -					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR166)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K5 5k86 (PR166)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 3:			// Model = 3:  K5 5k86 (PR 200 MHz) -					strcpy(CPUInfo.strModel, "AMD K5 5k86 (PR200)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K5 5k86 (PR200)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 6:			// Model = 6:  K6 -					strcpy(CPUInfo.strModel, "AMD K6 (0.30 micron)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K6 (0.30 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 7:			// Model = 7:  K6 (0.25 micron) -					strcpy(CPUInfo.strModel, "AMD K6 (0.25 micron)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K6 (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 8:			// Model = 8:  K6-2 -					strcpy(CPUInfo.strModel, "AMD K6-2");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K6-2", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 9:			// Model = 9:  K6-III -					strcpy(CPUInfo.strModel, "AMD K6-III");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K6-III", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 0xD:		// Model = 0xD:  K6-2+ / K6-III+ -					strcpy(CPUInfo.strModel, "AMD K6-2+ or K6-III+ (0.18 micron)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K6-2+ or K6-III+ (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);	/* Flawfinder: ignore */ -					break; -				default:		// ... -					strcpy(CPUInfo.strModel, "Unknown AMD K5 or K6 model");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K5 or K6 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -			} -			break; -		case 6:			// Family = 6:  K7 processor family (AMDs first good processors) -			switch (CPUInfo.uiModel) +#elif LL_DARWIN + +#include <mach/machine.h> +#include <sys/sysctl.h> + +class LLProcessorInfoDarwinImpl : public LLProcessorInfoImpl +{ +public: +	LLProcessorInfoDarwinImpl()  +	{ +		getCPUIDInfo(); +		uint64_t frequency = getSysctlInt64("hw.cpufrequency"); +		setInfo(eFrequency, (F64)frequency  / (F64)1000000); +	} + +	virtual ~LLProcessorInfoDarwinImpl() {} + +private: +	int getSysctlInt(const char* name) +   	{ +		int result = 0; +		size_t len = sizeof(int); +		int error = sysctlbyname(name, (void*)&result, &len, NULL, 0); +		return error == -1 ? 0 : result; +   	} + +	uint64_t getSysctlInt64(const char* name) +   	{ +		uint64_t value = 0; +		size_t size = sizeof(value); +		int result = sysctlbyname(name, (void*)&value, &size, NULL, 0); +		if ( result == 0 )  +		{  +			if ( size == sizeof( uint64_t ) )  +				;  +			else if ( size == sizeof( uint32_t ) )  +				value = (uint64_t)(( uint32_t *)&value);  +			else if ( size == sizeof( uint16_t ) )  +				value =  (uint64_t)(( uint16_t *)&value);  +			else if ( size == sizeof( uint8_t ) )  +				value =  (uint64_t)(( uint8_t *)&value);  +			else  			{ -				case 1:			// Athlon -					strcpy(CPUInfo.strModel, "AMD Athlon (0.25 micron)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Athlon (0.25 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 2:			// Athlon (0.18 micron) -					strcpy(CPUInfo.strModel, "AMD Athlon (0.18 micron)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Athlon (0.18 micron)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 3:			// Duron (Spitfire core) -					strcpy(CPUInfo.strModel, "AMD Duron (Spitfire)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Duron (Spitfire core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 4:			// Athlon (Thunderbird core) -					strcpy(CPUInfo.strModel, "AMD Athlon (Thunderbird)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Athlon (Thunderbird core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 6:			// Athlon MP / Mobile Athlon (Palomino core) -					strcpy(CPUInfo.strModel, "AMD Athlon MP/Mobile Athlon (Palomino)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Athlon MP/Mobile Athlon (Palomino core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				case 7:			// Mobile Duron (Morgan core) -					strcpy(CPUInfo.strModel, "AMD Mobile Duron (Morgan)");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD Mobile Duron (Morgan core)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; -				default:		// ... -					strcpy(CPUInfo.strModel, "Unknown AMD K7 model");		/* Flawfinder: ignore */ -					strncat(strCPUName, "AMD K7 (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -					break; +				LL_WARNS("Unknown type returned from sysctl!") << LL_ENDL;  			} -			break; -		default:		// ... -			strcpy(CPUInfo.strModel, "Unknown AMD model");		/* Flawfinder: ignore */ -			strncat(strCPUName, "AMD (Unknown model)", sizeof(strCPUName) - strlen(strCPUName) -1);		/* Flawfinder: ignore */ -			break; -    } - -	// Now we read the standard processor extension that are stored in the same -	// way the Intel standard extensions are -	GetStandardProcessorExtensions(); - -	// Then we check if theres an extended CPUID level support -	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000001) -	{ -		// If we can access the extended CPUID level 0x80000001 we get the -		// edx register -		__asm -		{ -			mov eax, 0x80000001 -			cpuid -			mov edxreg, edx  		} - -		// Now we can mask some AMD specific cpu extensions -		CPUInfo._Ext.EMMX_MultimediaExtensions					= CheckBit(edxreg, 22); -		CPUInfo._Ext.AA64_AMD64BitArchitecture					= CheckBit(edxreg, 29); -		CPUInfo._Ext._E3DNOW_InstructionExtensions				= CheckBit(edxreg, 30); -		CPUInfo._Ext._3DNOW_InstructionExtensions				= CheckBit(edxreg, 31); -	} - -	// After that we check if the processor supports the ext. CPUID level -	// 0x80000006 -	if (CPUInfo.MaxSupportedExtendedLevel >= 0x80000006) +				 +		return result == -1 ? 0 : value; +   	} +	 +	void getCPUIDInfo()  	{ -		// If it's present, we read it out -        __asm -		{ -            mov eax, 0x80000005 -			cpuid -			mov eaxreg, eax -			mov ebxreg, ebx -			mov ecxreg, ecx -			mov edxreg, edx -		} +		size_t len = 0; -		// Then we mask the L1 Data TLB information -		if ((ebxreg >> 16) && (eaxreg >> 16)) -		{ -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB / 2 MB / 4MB"); 	/*Flawfinder: ignore*/ -			CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; -			CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; -		} -		else if (eaxreg >> 16) -		{ -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "2 MB / 4MB");		/*Flawfinder: ignore*/ -			CPUInfo._Data.uiAssociativeWays = (eaxreg >> 24) & 0xFF; -			CPUInfo._Data.uiEntries = (eaxreg >> 16) & 0xFF; -		} -		else if (ebxreg >> 16) -		{ -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB");		/*Flawfinder: ignore*/ -			CPUInfo._Data.uiAssociativeWays = (ebxreg >> 24) & 0xFF; -			CPUInfo._Data.uiEntries = (ebxreg >> 16) & 0xFF; -		} -		if (CPUInfo._Data.uiAssociativeWays == 0xFF) -			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; - -		// Now the L1 Instruction/Code TLB information -		if ((ebxreg & 0xFFFF) && (eaxreg & 0xFFFF)) -		{ -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4MB");		/*Flawfinder: ignore*/ -			CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; -			CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; -		} -		else if (eaxreg & 0xFFFF) -		{ -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "2 MB / 4MB");		/*Flawfinder: ignore*/ -			CPUInfo._Instruction.uiAssociativeWays = (eaxreg >> 8) & 0xFF; -			CPUInfo._Instruction.uiEntries = eaxreg & 0xFF; -		} -		else if (ebxreg & 0xFFFF) -		{ -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB");	/*Flawfinder: ignore*/ -			CPUInfo._Instruction.uiAssociativeWays = (ebxreg >> 8) & 0xFF; -			CPUInfo._Instruction.uiEntries = ebxreg & 0xFF; -		} -		if (CPUInfo._Instruction.uiAssociativeWays == 0xFF) -			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; +		char cpu_brand_string[0x40]; +		len = sizeof(cpu_brand_string); +		memset(cpu_brand_string, 0, len); +		sysctlbyname("machdep.cpu.brand_string", (void*)cpu_brand_string, &len, NULL, 0); +		cpu_brand_string[0x3f] = 0; +		setInfo(eBrandName, cpu_brand_string); -		// Then we read the L1 data cache information -		if ((ecxreg >> 24) > 0) -		{ -			CPUInfo._L1.Data.bPresent = true; -			snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", ecxreg >> 24);		/* Flawfinder: ignore */ -			CPUInfo._L1.Data.uiAssociativeWays = (ecxreg >> 15) & 0xFF; -			CPUInfo._L1.Data.uiLineSize = ecxreg & 0xFF; -		} -		// After that we read the L2 instruction/code cache information -		if ((edxreg >> 24) > 0) -		{ -			CPUInfo._L1.Instruction.bPresent = true; -			snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", edxreg >> 24); 	/* Flawfinder: ignore */ -			CPUInfo._L1.Instruction.uiAssociativeWays = (edxreg >> 15) & 0xFF; -			CPUInfo._L1.Instruction.uiLineSize = edxreg & 0xFF; -		} - -		// Note: I'm not absolutely sure that the L1 page size code (the -		// 'if/else if/else if' structs above) really detects the real page -		// size for the TLB. Somebody should check it.... - -		// Now we read the ext. CPUID level 0x80000006 -        __asm -		{ -			mov eax, 0x80000006 -			cpuid -			mov eaxreg, eax -			mov ebxreg, ebx -			mov ecxreg, ecx -		} +		char cpu_vendor[0x20]; +		len = sizeof(cpu_vendor); +		memset(cpu_vendor, 0, len); +		sysctlbyname("machdep.cpu.vendor", (void*)cpu_vendor, &len, NULL, 0); +		cpu_vendor[0x1f] = 0; +		setInfo(eVendor, cpu_vendor); + +		setInfo(eStepping, getSysctlInt("machdep.cpu.stepping")); +		setInfo(eModel, getSysctlInt("machdep.cpu.model")); +		int family = getSysctlInt("machdep.cpu.family"); +		int ext_family = getSysctlInt("machdep.cpu.extfamily"); +		setInfo(eFamily, family); +		setInfo(eExtendedFamily, ext_family); +		setInfo(eFamilyName, compute_CPUFamilyName(cpu_vendor, family, ext_family)); +		setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); +		setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); +		setInfo(eType, 0); // ? where to find this? + +		//setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); +		//setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); +		setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); +		setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); +		setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); +		 +		uint64_t feature_info = getSysctlInt64("machdep.cpu.feature_bits"); +		S32 *feature_infos = (S32*)(&feature_info); +		 +		setConfig(eFeatureBits, feature_infos[0]); -		// We only mask the unified L2 cache masks (never heard of an -		// L2 cache that is divided in data and code parts) -		if (((ecxreg >> 12) & 0xF) > 0) +		for(unsigned int index = 0, bit = 1; index < eSSE3_Features; ++index, bit <<= 1)  		{ -			CPUInfo._L2.bPresent = true; -			snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", ecxreg >> 16);		/* Flawfinder: ignore */ -			switch ((ecxreg >> 12) & 0xF) +			if(feature_info & bit)  			{ -				case 1: -					CPUInfo._L2.uiAssociativeWays = 1; -					break; -				case 2: -					CPUInfo._L2.uiAssociativeWays = 2; -					break; -				case 4: -					CPUInfo._L2.uiAssociativeWays = 4; -					break; -				case 6: -					CPUInfo._L2.uiAssociativeWays = 8; -					break; -				case 8: -					CPUInfo._L2.uiAssociativeWays = 16; -					break; -				case 0xF: -					CPUInfo._L2.uiAssociativeWays = (unsigned int) -1; -					break; -				default: -					CPUInfo._L2.uiAssociativeWays = 0; -					break; +				setExtension(cpu_feature_names[index]);  			} -			CPUInfo._L2.uiLineSize = ecxreg & 0xFF;  		} -	} -	else -	{ -		// If we could not detect the ext. CPUID level 0x80000006 we -		// try to read the standard processor configuration. -		GetStandardProcessorConfiguration(); -	} -	// After reading we translate the configuration to strings -	TranslateProcessorConfiguration(); - -	// And finally exit -	return true; -#else -	return FALSE; -#endif -} - -// bool CProcessor::AnalyzeUnknownProcessor() -// ========================================== -// Private class function to analyze an unknown (No Intel or AMD) processor -/////////////////////////////////////////////////////////////////////////// -bool CProcessor::AnalyzeUnknownProcessor() -{ -#if LL_WINDOWS -	unsigned long eaxreg, ebxreg; - -	// We check if the CPUID command is available -	if (!CheckCPUIDPresence()) -		return false; - -	// First of all we read the standard CPUID level 0x00000001 -	// This level should be available on every x86-processor clone -	__asm -	{ -        mov eax, 1 -		cpuid -		mov eaxreg, eax -		mov ebxreg, ebx -	} -	// Then we mask the processor model, family, type and stepping -	CPUInfo.uiStepping = eaxreg & 0xF; -	CPUInfo.uiModel    = (eaxreg >> 4) & 0xF; -	CPUInfo.uiFamily   = (eaxreg >> 8) & 0xF; -	CPUInfo.uiType     = (eaxreg >> 12) & 0x3; - -	// To have complete information we also mask the brand id -	CPUInfo.uiBrandID  = ebxreg & 0xF; - -	// Then we get the standard processor extensions -	GetStandardProcessorExtensions(); - -	// Now we mark everything we do not know as unknown -	strcpy(strCPUName, "Unknown");		/*Flawfinder: ignore*/ - -	strcpy(CPUInfo._Data.strTLB, "Unknown");	/*Flawfinder: ignore*/ -	strcpy(CPUInfo._Instruction.strTLB, "Unknown");		/*Flawfinder: ignore*/ -	 -	strcpy(CPUInfo._Trace.strCache, "Unknown");		/*Flawfinder: ignore*/ -	strcpy(CPUInfo._L1.Data.strCache, "Unknown");		/*Flawfinder: ignore*/ -	strcpy(CPUInfo._L1.Instruction.strCache, "Unknown");	/*Flawfinder: ignore*/ -	strcpy(CPUInfo._L2.strCache, "Unknown");		/*Flawfinder: ignore*/ -	strcpy(CPUInfo._L3.strCache, "Unknown");		/*Flawfinder: ignore*/ - -	strcpy(CPUInfo.strProcessorSerial, "Unknown / Not supported");	/*Flawfinder: ignore*/ - -	// For the family, model and brand id we can only print the numeric value -	snprintf(CPUInfo.strBrandID, sizeof(CPUInfo.strBrandID), "Brand-ID number %d", CPUInfo.uiBrandID);		/* Flawfinder: ignore */ -	snprintf(CPUInfo.strFamily, sizeof(CPUInfo.strFamily), "Family number %d", CPUInfo.uiFamily);		/* Flawfinder: ignore */ -	snprintf(CPUInfo.strModel, sizeof(CPUInfo.strModel), "Model number %d", CPUInfo.uiModel);		/* Flawfinder: ignore */ - -	// And thats it -	return true; -#else -	return FALSE; -#endif -} - -// bool CProcessor::CheckCPUIDPresence() -// ===================================== -// This function checks if the CPUID command is available on the current -// processor -//////////////////////////////////////////////////////////////////////// -bool CProcessor::CheckCPUIDPresence() -{ -#if LL_WINDOWS -	unsigned long BitChanged; -	 -	// We've to check if we can toggle the flag register bit 21 -	// If we can't the processor does not support the CPUID command -	__asm -	{ -		pushfd -		pop eax -		mov ebx, eax -		xor eax, 0x00200000  -		push eax -		popfd -		pushfd -		pop eax -		xor eax,ebx  -		mov BitChanged, eax -	} -	return ((BitChanged) ? true : false); -#else -	return FALSE; -#endif -} +		// *NOTE:Mani - I didn't find any docs that assure me that machdep.cpu.feature_bits will always be +		// The feature bits I think it is. Here's a test: +#ifndef LL_RELEASE_FOR_DOWNLOAD +	#if defined(__i386__) && defined(__PIC__) +			/* %ebx may be the PIC register.  */ +		#define __cpuid(level, a, b, c, d)			\ +		__asm__ ("xchgl\t%%ebx, %1\n\t"			\ +				"cpuid\n\t"					\ +				"xchgl\t%%ebx, %1\n\t"			\ +				: "=a" (a), "=r" (b), "=c" (c), "=d" (d)	\ +				: "0" (level)) +	#else +		#define __cpuid(level, a, b, c, d)			\ +		__asm__ ("cpuid\n\t"					\ +				 : "=a" (a), "=b" (b), "=c" (c), "=d" (d)	\ +				 : "0" (level)) +	#endif + +		unsigned int eax, ebx, ecx, edx; +		__cpuid(0x1, eax, ebx, ecx, edx); +		if(feature_infos[0] != (S32)edx) +		{ +			llerrs << "machdep.cpu.feature_bits doesn't match expected cpuid result!" << llendl; +		}  +#endif // LL_RELEASE_FOR_DOWNLOAD 	 -// void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -// =============================================================== -// This function (or switch ?!) just translates a one-byte processor configuration -// byte to understandable values -////////////////////////////////////////////////////////////////////////////////// -void CProcessor::DecodeProcessorConfiguration(unsigned int cfg) -{ -	// First we ensure that there's only one single byte -	cfg &= 0xFF; -	// Then we do a big switch -	switch(cfg) -	{ -		case 0:			// cfg = 0:  Unused -			break; -		case 0x1:		// cfg = 0x1:  code TLB present, 4 KB pages, 4 ways, 32 entries -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB");	/*Flawfinder: ignore*/ -			CPUInfo._Instruction.uiAssociativeWays = 4; -			CPUInfo._Instruction.uiEntries = 32; -			break; -		case 0x2:		// cfg = 0x2:  code TLB present, 4 MB pages, fully associative, 2 entries -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 MB");	/*Flawfinder: ignore*/ -			CPUInfo._Instruction.uiAssociativeWays = 4; -			CPUInfo._Instruction.uiEntries = 2; -			break; -		case 0x3:		// cfg = 0x3:  data TLB present, 4 KB pages, 4 ways, 64 entries -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB");		/*Flawfinder: ignore*/ -			CPUInfo._Data.uiAssociativeWays = 4; -			CPUInfo._Data.uiEntries = 64; -			break; -		case 0x4:		// cfg = 0x4:  data TLB present, 4 MB pages, 4 ways, 8 entries -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 MB");	/*Flawfinder: ignore*/ -			CPUInfo._Data.uiAssociativeWays = 4; -			CPUInfo._Data.uiEntries = 8; -			break; -		case 0x6:		// cfg = 0x6:  code L1 cache present, 8 KB, 4 ways, 32 byte lines -			CPUInfo._L1.Instruction.bPresent = true; -			strcpy(CPUInfo._L1.Instruction.strSize, "8 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L1.Instruction.uiAssociativeWays = 4; -			CPUInfo._L1.Instruction.uiLineSize = 32; -			break; -		case 0x8:		// cfg = 0x8:  code L1 cache present, 16 KB, 4 ways, 32 byte lines -			CPUInfo._L1.Instruction.bPresent = true; -			strcpy(CPUInfo._L1.Instruction.strSize, "16 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L1.Instruction.uiAssociativeWays = 4; -			CPUInfo._L1.Instruction.uiLineSize = 32; -			break; -		case 0xA:		// cfg = 0xA:  data L1 cache present, 8 KB, 2 ways, 32 byte lines -			CPUInfo._L1.Data.bPresent = true; -			strcpy(CPUInfo._L1.Data.strSize, "8 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L1.Data.uiAssociativeWays = 2; -			CPUInfo._L1.Data.uiLineSize = 32; -			break; -		case 0xC:		// cfg = 0xC:  data L1 cache present, 16 KB, 4 ways, 32 byte lines -			CPUInfo._L1.Data.bPresent = true; -			strcpy(CPUInfo._L1.Data.strSize, "16 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L1.Data.uiAssociativeWays = 4; -			CPUInfo._L1.Data.uiLineSize = 32; -			break; -		case 0x22:		// cfg = 0x22:  code and data L3 cache present, 512 KB, 4 ways, 64 byte lines, sectored -			CPUInfo._L3.bPresent = true; -			strcpy(CPUInfo._L3.strSize, "512 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L3.uiAssociativeWays = 4; -			CPUInfo._L3.uiLineSize = 64; -			CPUInfo._L3.bSectored = true; -			break; -		case 0x23:		// cfg = 0x23:  code and data L3 cache present, 1024 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L3.bPresent = true; -			strcpy(CPUInfo._L3.strSize, "1024 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L3.uiAssociativeWays = 8; -			CPUInfo._L3.uiLineSize = 64; -			CPUInfo._L3.bSectored = true; -			break; -		case 0x25:		// cfg = 0x25:  code and data L3 cache present, 2048 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L3.bPresent = true; -			strcpy(CPUInfo._L3.strSize, "2048 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L3.uiAssociativeWays = 8; -			CPUInfo._L3.uiLineSize = 64; -			CPUInfo._L3.bSectored = true; -			break; -		case 0x29:		// cfg = 0x29:  code and data L3 cache present, 4096 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L3.bPresent = true; -			strcpy(CPUInfo._L3.strSize, "4096 KB");	/*Flawfinder: ignore*/ -			CPUInfo._L3.uiAssociativeWays = 8; -			CPUInfo._L3.uiLineSize = 64; -			CPUInfo._L3.bSectored = true; -			break; -		case 0x40:		// cfg = 0x40:  no integrated L2 cache (P6 core) or L3 cache (P4 core) -			break; -		case 0x41:		// cfg = 0x41:  code and data L2 cache present, 128 KB, 4 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "128 KB");		/*Flawfinder: ignore*/ -			CPUInfo._L2.uiAssociativeWays = 4; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x42:		// cfg = 0x42:  code and data L2 cache present, 256 KB, 4 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "256 KB");		/*Flawfinder: ignore*/ -			CPUInfo._L2.uiAssociativeWays = 4; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x43:		// cfg = 0x43:  code and data L2 cache present, 512 KB, 4 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "512 KB");		/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 4; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x44:		// cfg = 0x44:  code and data L2 cache present, 1024 KB, 4 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 4; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x45:		// cfg = 0x45:  code and data L2 cache present, 2048 KB, 4 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "2 MB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 4; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x50:		// cfg = 0x50:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 64 entries -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Instruction.uiEntries = 64; -			break; -		case 0x51:		// cfg = 0x51:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 128 entries -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Instruction.uiEntries = 128; -			break; -		case 0x52:		// cfg = 0x52:  code TLB present, 4 KB / 4 MB / 2 MB pages, fully associative, 256 entries -			CPUInfo._Instruction.bPresent = true; -			strcpy(CPUInfo._Instruction.strPageSize, "4 KB / 2 MB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Instruction.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Instruction.uiEntries = 256; -			break; -		case 0x5B:		// cfg = 0x5B:  data TLB present, 4 KB / 4 MB pages, fully associative, 64 entries -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Data.uiEntries = 64; -			break; -		case 0x5C:		// cfg = 0x5C:  data TLB present, 4 KB / 4 MB pages, fully associative, 128 entries -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Data.uiEntries = 128; -			break; -		case 0x5d:		// cfg = 0x5D:  data TLB present, 4 KB / 4 MB pages, fully associative, 256 entries -			CPUInfo._Data.bPresent = true; -			strcpy(CPUInfo._Data.strPageSize, "4 KB / 4 MB");	/* Flawfinder: ignore */ -			CPUInfo._Data.uiAssociativeWays = (unsigned int) -1; -			CPUInfo._Data.uiEntries = 256; -			break; -		case 0x66:		// cfg = 0x66:  data L1 cache present, 8 KB, 4 ways, 64 byte lines, sectored -			CPUInfo._L1.Data.bPresent = true; -			strcpy(CPUInfo._L1.Data.strSize, "8 KB");	/* Flawfinder: ignore */ -			CPUInfo._L1.Data.uiAssociativeWays = 4; -			CPUInfo._L1.Data.uiLineSize = 64; -			break; -		case 0x67:		// cfg = 0x67:  data L1 cache present, 16 KB, 4 ways, 64 byte lines, sectored -			CPUInfo._L1.Data.bPresent = true; -			strcpy(CPUInfo._L1.Data.strSize, "16 KB");	/* Flawfinder: ignore */ -			CPUInfo._L1.Data.uiAssociativeWays = 4; -			CPUInfo._L1.Data.uiLineSize = 64; -			break; -		case 0x68:		// cfg = 0x68:  data L1 cache present, 32 KB, 4 ways, 64 byte lines, sectored -			CPUInfo._L1.Data.bPresent = true; -			strcpy(CPUInfo._L1.Data.strSize, "32 KB");	/* Flawfinder: ignore */ -			CPUInfo._L1.Data.uiAssociativeWays = 4; -			CPUInfo._L1.Data.uiLineSize = 64; -			break; -		case 0x70:		// cfg = 0x70:  trace L1 cache present, 12 KuOPs, 4 ways -			CPUInfo._Trace.bPresent = true; -			strcpy(CPUInfo._Trace.strSize, "12 K-micro-ops");	/* Flawfinder: ignore */ -			CPUInfo._Trace.uiAssociativeWays = 4; -			break; -		case 0x71:		// cfg = 0x71:  trace L1 cache present, 16 KuOPs, 4 ways -			CPUInfo._Trace.bPresent = true; -			strcpy(CPUInfo._Trace.strSize, "16 K-micro-ops");	/* Flawfinder: ignore */ -			CPUInfo._Trace.uiAssociativeWays = 4; -			break; -		case 0x72:		// cfg = 0x72:  trace L1 cache present, 32 KuOPs, 4 ways -			CPUInfo._Trace.bPresent = true; -			strcpy(CPUInfo._Trace.strSize, "32 K-micro-ops");	/* Flawfinder: ignore */ -			CPUInfo._Trace.uiAssociativeWays = 4; -			break; -		case 0x79:		// cfg = 0x79:  code and data L2 cache present, 128 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "128 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 64; -			CPUInfo._L2.bSectored = true; -			break; -		case 0x7A:		// cfg = 0x7A:  code and data L2 cache present, 256 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "256 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 64; -			CPUInfo._L2.bSectored = true; -			break; -		case 0x7B:		// cfg = 0x7B:  code and data L2 cache present, 512 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "512 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 64; -			CPUInfo._L2.bSectored = true; -			break; -		case 0x7C:		// cfg = 0x7C:  code and data L2 cache present, 1024 KB, 8 ways, 64 byte lines, sectored -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 64; -			CPUInfo._L2.bSectored = true; -			break; -		case 0x81:		// cfg = 0x81:  code and data L2 cache present, 128 KB, 8 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "128 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x82:		// cfg = 0x82:  code and data L2 cache present, 256 KB, 8 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "256 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x83:		// cfg = 0x83:  code and data L2 cache present, 512 KB, 8 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "512 KB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x84:		// cfg = 0x84:  code and data L2 cache present, 1024 KB, 8 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "1 MB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 32; -			break; -		case 0x85:		// cfg = 0x85:  code and data L2 cache present, 2048 KB, 8 ways, 32 byte lines -			CPUInfo._L2.bPresent = true; -			strcpy(CPUInfo._L2.strSize, "2 MB");	/* Flawfinder: ignore */ -			CPUInfo._L2.uiAssociativeWays = 8; -			CPUInfo._L2.uiLineSize = 32; -			break; +		uint64_t ext_feature_info = getSysctlInt64("machdep.cpu.extfeature_bits"); +		S32 *ext_feature_infos = (S32*)(&ext_feature_info); +		setConfig(eExtFeatureBits, ext_feature_infos[0]);  	} -} +}; -FORCEINLINE static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ -	// We define 0xFFFFFFFF (= -1) as fully associative -    if (uiWays == ((unsigned int) -1)) -		strcpy(buf, "fully associative");	/* Flawfinder: ignore */ -	else -	{ -		if (uiWays == 1)			// A one way associative cache is just direct mapped -			strcpy(buf, "direct mapped");	/* Flawfinder: ignore */ -		else if (uiWays == 0)		// This should not happen... -			strcpy(buf, "unknown associative ways");	/* Flawfinder: ignore */ -		else						// The x-way associative cache -			sprintf(buf, "%d ways associative", uiWays);	/* Flawfinder: ignore */ -	} -	// To ease the function use we return the buffer -	return buf; -} -FORCEINLINE static void TranslateTLB(ProcessorTLB *tlb) -{ -	char buf[64];	/* Flawfinder: ignore */ +#elif LL_LINUX +const char CPUINFO_FILE[] = "/proc/cpuinfo"; -	// We just check if the TLB is present -	if (tlb->bPresent) -        snprintf(tlb->strTLB,sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);	/* Flawfinder: ignore */ -	else -        strcpy(tlb->strTLB, "Not present");	/* Flawfinder: ignore */ -} -FORCEINLINE static void TranslateCache(ProcessorCache *cache) +class LLProcessorInfoLinuxImpl : public LLProcessorInfoImpl  { -	char buf[64];	/* Flawfinder: ignore */ - -	// We just check if the cache is present -    if (cache->bPresent) -	{ -		// If present we construct the string -		snprintf(cache->strCache, sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);	/* Flawfinder: ignore */ -		if (cache->bSectored) -			strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);	/* Flawfinder: ignore */ -	} -	else +public: +	LLProcessorInfoLinuxImpl()   	{ -		// Else we just say "Not present" -		strcpy(cache->strCache, "Not present");	/* Flawfinder: ignore */ +		get_proc_cpuinfo();  	} -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ -	// We just call the small functions defined above -	TranslateTLB(&CPUInfo._Data); -	TranslateTLB(&CPUInfo._Instruction); -	TranslateCache(&CPUInfo._Trace); +	virtual ~LLProcessorInfoLinuxImpl() {} +private: -	TranslateCache(&CPUInfo._L1.Instruction); -	TranslateCache(&CPUInfo._L1.Data); -	TranslateCache(&CPUInfo._L2); -	TranslateCache(&CPUInfo._L3); -} - -// void CProcessor::GetStandardProcessorConfiguration() -// ==================================================== -// Private class function to read the standard processor configuration -////////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorConfiguration() -{ -#if LL_WINDOWS -	unsigned long eaxreg, ebxreg, ecxreg, edxreg; - -	// We check if the CPUID function is available -	if (!CheckCPUIDPresence()) -		return; - -	// First we check if the processor supports the standard -	// CPUID level 0x00000002 -	if (CPUInfo.MaxSupportedLevel >= 2) +	void get_proc_cpuinfo()  	{ -		// Now we go read the std. CPUID level 0x00000002 the first time -		unsigned long count, num = 255; -		for (count = 0; count < num; count++) +		std::map< std::string, std::string > cpuinfo; +		LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); +		if(cpuinfo_fp)  		{ -			__asm -			{ -				mov eax, 2 -				cpuid -				mov eaxreg, eax -				mov ebxreg, ebx -				mov ecxreg, ecx -				mov edxreg, edx -			} -			// We have to repeat this reading for 'num' times -			num = eaxreg & 0xFF; - -			// Then we call the big decode switch function -			DecodeProcessorConfiguration(eaxreg >> 8); -			DecodeProcessorConfiguration(eaxreg >> 16); -			DecodeProcessorConfiguration(eaxreg >> 24); - -			// If ebx contains additional data we also decode it -			if ((ebxreg & 0x80000000) == 0) +			char line[MAX_STRING]; +			memset(line, 0, MAX_STRING); +			while(fgets(line, MAX_STRING, cpuinfo_fp))  			{ -				DecodeProcessorConfiguration(ebxreg); -				DecodeProcessorConfiguration(ebxreg >> 8); -				DecodeProcessorConfiguration(ebxreg >> 16); -				DecodeProcessorConfiguration(ebxreg >> 24); -			} -			// And also the ecx register -			if ((ecxreg & 0x80000000) == 0) -			{ -				DecodeProcessorConfiguration(ecxreg); -				DecodeProcessorConfiguration(ecxreg >> 8); -				DecodeProcessorConfiguration(ecxreg >> 16); -				DecodeProcessorConfiguration(ecxreg >> 24); -			} -			// At last the edx processor register -			if ((edxreg & 0x80000000) == 0) -			{ -				DecodeProcessorConfiguration(edxreg); -				DecodeProcessorConfiguration(edxreg >> 8); -				DecodeProcessorConfiguration(edxreg >> 16); -				DecodeProcessorConfiguration(edxreg >> 24); +				// /proc/cpuinfo on Linux looks like: +				// name\t*: value\n +				char* tabspot = strchr( line, '\t' ); +				if (tabspot == NULL) +					continue; +				char* colspot = strchr( tabspot, ':' ); +				if (colspot == NULL) +					continue; +				char* spacespot = strchr( colspot, ' ' ); +				if (spacespot == NULL) +					continue; +				char* nlspot = strchr( line, '\n' ); +				if (nlspot == NULL) +					nlspot = line + strlen( line ); // Fallback to terminating NUL +				std::string linename( line, tabspot ); +				std::string llinename(linename); +				LLStringUtil::toLower(llinename); +				std::string lineval( spacespot + 1, nlspot ); +				cpuinfo[ llinename ] = lineval;  			} +			fclose(cpuinfo_fp); +		} +# if LL_X86 + +// *NOTE:Mani - eww, macros! srry. +#define LLPI_SET_INFO_STRING(llpi_id, cpuinfo_id) \ +		if (!cpuinfo[cpuinfo_id].empty()) \ +		{ setInfo(llpi_id, cpuinfo[cpuinfo_id]);} + +#define LLPI_SET_INFO_INT(llpi_id, cpuinfo_id) \ +		{\ +			S32 result; \ +			if (!cpuinfo[cpuinfo_id].empty() \ +				&& LLStringUtil::convertToS32(cpuinfo[cpuinfo_id], result))	\ +		    { setInfo(llpi_id, result);} \ +		} +		 +		F64 mhz; +		if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) +			&& 200.0 < mhz && mhz < 10000.0) +		{ +		    setInfo(eFrequency,(F64)(mhz));  		} -	} -#endif -} -// void CProcessor::GetStandardProcessorExtensions() -// ================================================= -// Private class function to read the standard processor extensions -/////////////////////////////////////////////////////////////////// -void CProcessor::GetStandardProcessorExtensions() -{ -#if LL_WINDOWS -	unsigned long ebxreg, edxreg; +		LLPI_SET_INFO_STRING(eBrandName, "model name");		 +		LLPI_SET_INFO_STRING(eVendor, "vendor_id"); -	// We check if the CPUID command is available -	if (!CheckCPUIDPresence()) -		return; -	// We just get the standard CPUID level 0x00000001 which should be -	// available on every x86 processor -	__asm -	{ -		mov eax, 1 -		cpuid -		mov ebxreg, ebx -		mov edxreg, edx -	} -     -	// Then we mask some bits -	CPUInfo._Ext.FPU_FloatingPointUnit							= CheckBit(edxreg, 0); -	CPUInfo._Ext.VME_Virtual8086ModeEnhancements				= CheckBit(edxreg, 1); -	CPUInfo._Ext.DE_DebuggingExtensions							= CheckBit(edxreg, 2); -	CPUInfo._Ext.PSE_PageSizeExtensions							= CheckBit(edxreg, 3); -	CPUInfo._Ext.TSC_TimeStampCounter							= CheckBit(edxreg, 4); -	CPUInfo._Ext.MSR_ModelSpecificRegisters						= CheckBit(edxreg, 5); -	CPUInfo._Ext.PAE_PhysicalAddressExtension					= CheckBit(edxreg, 6); -	CPUInfo._Ext.MCE_MachineCheckException						= CheckBit(edxreg, 7); -	CPUInfo._Ext.CX8_COMPXCHG8B_Instruction						= CheckBit(edxreg, 8); -	CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController	= CheckBit(edxreg, 9); -	CPUInfo._Ext.APIC_ID = (ebxreg >> 24) & 0xFF; -	CPUInfo._Ext.SEP_FastSystemCall								= CheckBit(edxreg, 11); -	CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters					= CheckBit(edxreg, 12); -	CPUInfo._Ext.PGE_PTE_GlobalFlag								= CheckBit(edxreg, 13); -	CPUInfo._Ext.MCA_MachineCheckArchitecture					= CheckBit(edxreg, 14); -	CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions		= CheckBit(edxreg, 15); -	CPUInfo._Ext.FGPAT_PageAttributeTable						= CheckBit(edxreg, 16); -	CPUInfo._Ext.PSE36_36bitPageSizeExtension					= CheckBit(edxreg, 17); -	CPUInfo._Ext.PN_ProcessorSerialNumber						= CheckBit(edxreg, 18); -	CPUInfo._Ext.CLFSH_CFLUSH_Instruction						= CheckBit(edxreg, 19); -	CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize = (ebxreg >> 8) & 0xFF; -	CPUInfo._Ext.DS_DebugStore									= CheckBit(edxreg, 21); -	CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl				= CheckBit(edxreg, 22); -	CPUInfo._Ext.MMX_MultimediaExtensions						= CheckBit(edxreg, 23); -	CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore	= CheckBit(edxreg, 24); -	CPUInfo._Ext.SSE_StreamingSIMD_Extensions					= CheckBit(edxreg, 25); -	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions					= CheckBit(edxreg, 26); -	CPUInfo._Ext.Altivec_Extensions = false; -	CPUInfo._Ext.SS_SelfSnoop									= CheckBit(edxreg, 27); -	CPUInfo._Ext.HT_HyperThreading								= CheckBit(edxreg, 28); -	CPUInfo._Ext.HT_HyterThreadingSiblings = (ebxreg >> 16) & 0xFF; -	CPUInfo._Ext.TM_ThermalMonitor								= CheckBit(edxreg, 29); -	CPUInfo._Ext.IA64_Intel64BitArchitecture					= CheckBit(edxreg, 30); -#endif -} +		LLPI_SET_INFO_INT(eStepping, "stepping"); +		LLPI_SET_INFO_INT(eModel, "model"); -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -#if LL_WINDOWS -	unsigned long eaxreg, ebxreg, ecxreg, edxreg; +		 +		S32 family;							  +		if (!cpuinfo["cpu family"].empty()  +			&& LLStringUtil::convertToS32(cpuinfo["cpu family"], family))	 +		{  +			setInfo(eFamily, family); +		} -	// First of all we check if the CPUID command is available -	if (!CheckCPUIDPresence()) -		return NULL; +		setInfo(eFamilyName, compute_CPUFamilyName(cpuinfo["vendor_id"].c_str(), family)); -	// We read the standard CPUID level 0x00000000 which should -	// be available on every x86 processor -	__asm -	{ -		mov eax, 0 -		cpuid -		mov eaxreg, eax -		mov ebxreg, ebx -		mov edxreg, edx -		mov ecxreg, ecx -	} -	// Then we connect the single register values to the vendor string -	*((unsigned long *) CPUInfo.strVendor) = ebxreg; -	*((unsigned long *) (CPUInfo.strVendor+4)) = edxreg; -	*((unsigned long *) (CPUInfo.strVendor+8)) = ecxreg; -	// Null terminate for string comparisons below. -	CPUInfo.strVendor[12] = 0; - -	// We can also read the max. supported standard CPUID level -	CPUInfo.MaxSupportedLevel = eaxreg & 0xFFFF; - -	// Then we read the ext. CPUID level 0x80000000 -	__asm -	{ -        mov eax, 0x80000000 -		cpuid -		mov eaxreg, eax -	} -	// ...to check the max. supportted extended CPUID level -	CPUInfo.MaxSupportedExtendedLevel = eaxreg; - -	// Then we switch to the specific processor vendors -	// See http://www.sandpile.org/ia32/cpuid.htm -	if (!strcmp(CPUInfo.strVendor, "GenuineIntel")) -	{ -		AnalyzeIntelProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "AuthenticAMD")) -	{ -		AnalyzeAMDProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "UMC UMC UMC")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "CyrixInstead")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "NexGenDriven")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "CentaurHauls")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "RiseRiseRise")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "SiS SiS SiS")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "GenuineTMx86")) -	{ -		// Transmeta -		AnalyzeUnknownProcessor(); -	} -	else if (!strcmp(CPUInfo.strVendor, "Geode by NSC")) -	{ -		AnalyzeUnknownProcessor(); -	} -	else -	{ -		AnalyzeUnknownProcessor(); -	} -#endif -	// After all we return the class CPUInfo member var -	return (&CPUInfo); -} +		// setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); +		// setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); +		// setInfo(eType, 0); // ? where to find this? -#elif LL_SOLARIS -#include <kstat.h> - -#if defined(__i386) -#include <sys/auxv.h> -#endif - -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ -	uqwFrequency = 0; -	strCPUName[0] = 0; -	memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ -	if(uqwFrequency == 0){ -		GetCPUInfo(); -	} - -	return uqwFrequency; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -					// In Solaris the CPU info is in the kstats -					// try "psrinfo" or "kstat cpu_info" to see all -					// that's available -	int ncpus=0, i;  -	kstat_ctl_t	*kc; -	kstat_t 	*ks; -	kstat_named_t   *ksinfo, *ksi; -	kstat_t 	*CPU_stats_list; - -	kc = kstat_open(); - -	if((int)kc == -1){ -		llwarns << "kstat_open(0 failed!" << llendl; -		return (&CPUInfo); -	} - -	for (ks = kc->kc_chain; ks != NULL; ks = ks->ks_next) { -		if (strncmp(ks->ks_module, "cpu_info", 8) == 0 && -			strncmp(ks->ks_name, "cpu_info", 8) == 0) -			ncpus++; -	} -	 -	if(ncpus < 1){ -		llwarns << "No cpus found in kstats!" << llendl; -		return (&CPUInfo); -	} - -	for (ks = kc->kc_chain; ks; ks = ks->ks_next) { -		if (strncmp(ks->ks_module, "cpu_info", 8) == 0  -		&&  strncmp(ks->ks_name, "cpu_info", 8) == 0  -		&&  kstat_read(kc, ks, NULL) != -1){      -			CPU_stats_list = ks;	// only looking at the first CPU -			 -			break; -		} -	} - -	if(ncpus > 1) -        	snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpus);  - -	kstat_read(kc, CPU_stats_list, NULL); -	ksinfo = (kstat_named_t *)CPU_stats_list->ks_data; -	for(i=0; i < (int)(CPU_stats_list->ks_ndata); ++i){ // Walk the kstats for this cpu gathering what we need -		ksi = ksinfo++; -		if(!strcmp(ksi->name, "brand")){ -			strncat(strCPUName, (char *)KSTAT_NAMED_STR_PTR(ksi), -				sizeof(strCPUName)-strlen(strCPUName)-1); -			strncat(CPUInfo.strFamily, (char *)KSTAT_NAMED_STR_PTR(ksi), -				sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1); -			strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1); -			CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; -			// DEBUG llinfos << "CPU brand: " << strCPUName << llendl; -			continue; -		} +		//setConfig(eCLFLUSHCacheLineSize, ((cpu_info[1] >> 8) & 0xff) * 8); +		//setConfig(eAPICPhysicalID, (cpu_info[1] >> 24) & 0xff); +		//setConfig(eCacheLineSize, getSysctlInt("machdep.cpu.cache.linesize")); +		//setConfig(eL2Associativity, getSysctlInt("machdep.cpu.cache.L2_associativity")); +		//setConfig(eCacheSizeK, getSysctlInt("machdep.cpu.cache.size")); +		 +		// Read extensions +		std::string flags = " " + cpuinfo["flags"] + " "; +		LLStringUtil::toLower(flags); -		if(!strcmp(ksi->name, "clock_MHz")){ -#if defined(__sparc) -			llinfos << "Raw kstat clock rate is: " << ksi->value.l << llendl; -			uqwFrequency = (F64)(ksi->value.l * 1000000); -#else -			uqwFrequency = (F64)(ksi->value.i64 * 1000000); -#endif -			//DEBUG llinfos << "CPU frequency: " << uqwFrequency << llendl; -			continue; +		if( flags.find( " sse " ) != std::string::npos ) +		{ +			setExtension(cpu_feature_names[eSSE_Ext]);   		} -#if defined(__i386) -		if(!strcmp(ksi->name, "vendor_id")){ -			strncpy(CPUInfo.strVendor, (char *)KSTAT_NAMED_STR_PTR(ksi), sizeof(CPUInfo.strVendor)-1); -			// DEBUG llinfos << "CPU vendor: " << CPUInfo.strVendor << llendl; -			continue; +		if( flags.find( " sse2 " ) != std::string::npos ) +		{ +			setExtension(cpu_feature_names[eSSE2_Ext]);  		} -#endif -	} - -	kstat_close(kc); - -#if defined(__sparc)		// SPARC does not define a vendor string in kstat -	strncpy(CPUInfo.strVendor, "Sun Microsystems, Inc.", sizeof(CPUInfo.strVendor)-1); -#endif - -	// DEBUG llinfo << "The system has " << ncpus << " CPUs with a clock rate of " <<  uqwFrequency << "MHz." << llendl; -	 -#if defined (__i386)  //  we really don't care about the CPU extensions on SPARC but on x86... - -	// Now get cpu extensions - -	uint_t ui; - -	(void) getisax(&ui, 1); -	if(ui & AV_386_FPU) -		CPUInfo._Ext.FPU_FloatingPointUnit = true; -	if(ui & AV_386_CX8) -		CPUInfo._Ext.CX8_COMPXCHG8B_Instruction = true; -	if(ui & AV_386_MMX) -		CPUInfo._Ext.MMX_MultimediaExtensions = true; -	if(ui & AV_386_AMD_MMX) -		CPUInfo._Ext.MMX_MultimediaExtensions = true; -	if(ui & AV_386_FXSR) -		CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore = true; -	if(ui & AV_386_SSE) -		 CPUInfo._Ext.SSE_StreamingSIMD_Extensions = true; -	if(ui & AV_386_SSE2) -		CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = true; -/* Left these here since they may get used later -	if(ui & AV_386_SSE3) -		CPUInfo._Ext.... = true; -	if(ui & AV_386_AMD_3DNow) -		CPUInfo._Ext.... = true; -	if(ui & AV_386_AMD_3DNowx) -		CPUInfo._Ext.... = true; -*/ -#endif -	return (&CPUInfo); -} - -#else -// LL_DARWIN - -#include <mach/machine.h> -#include <sys/sysctl.h> - -static char *TranslateAssociativeWays(unsigned int uiWays, char *buf) -{ -	// We define 0xFFFFFFFF (= -1) as fully associative -    if (uiWays == ((unsigned int) -1)) -		strcpy(buf, "fully associative");	/* Flawfinder: ignore */ -	else -	{ -		if (uiWays == 1)			// A one way associative cache is just direct mapped -			strcpy(buf, "direct mapped");	/* Flawfinder: ignore */ -		else if (uiWays == 0)		// This should not happen... -			strcpy(buf, "unknown associative ways");	/* Flawfinder: ignore */ -		else						// The x-way associative cache -			sprintf(buf, "%d ways associative", uiWays);	/* Flawfinder: ignore */ +# endif // LL_X86  	} -	// To ease the function use we return the buffer -	return buf; -} -static void TranslateTLB(ProcessorTLB *tlb) -{ -	char buf[64];	/* Flawfinder: ignore */ - -	// We just check if the TLB is present -	if (tlb->bPresent) -        snprintf(tlb->strTLB, sizeof(tlb->strTLB), "%s page size, %s, %d entries", tlb->strPageSize, TranslateAssociativeWays(tlb->uiAssociativeWays, buf), tlb->uiEntries);	/* Flawfinder: ignore */ -	else -        strcpy(tlb->strTLB, "Not present");	/* Flawfinder: ignore */ -} -static void TranslateCache(ProcessorCache *cache) -{ -	char buf[64];	/* Flawfinder: ignore */ -	// We just check if the cache is present -    if (cache->bPresent) +	std::string getCPUFeatureDescription() const   	{ -		// If present we construct the string -		snprintf(cache->strCache,sizeof(cache->strCache), "%s cache size, %s, %d bytes line size", cache->strSize, TranslateAssociativeWays(cache->uiAssociativeWays, buf), cache->uiLineSize);	/* Flawfinder: ignore */ -		if (cache->bSectored) -			strncat(cache->strCache, ", sectored", sizeof(cache->strCache)-strlen(cache->strCache)-1);	/* Flawfinder: ignore */ -	} -	else -	{ -		// Else we just say "Not present" -		strcpy(cache->strCache, "Not present");	/* Flawfinder: ignore */ -	} -} - -// void CProcessor::TranslateProcessorConfiguration() -// ================================================== -// Private class function to translate the processor configuration values -// to strings -///////////////////////////////////////////////////////////////////////// -void CProcessor::TranslateProcessorConfiguration() -{ -	// We just call the small functions defined above -	TranslateTLB(&CPUInfo._Data); -	TranslateTLB(&CPUInfo._Instruction); - -	TranslateCache(&CPUInfo._Trace); +		std::ostringstream s; -	TranslateCache(&CPUInfo._L1.Instruction); -	TranslateCache(&CPUInfo._L1.Data); -	TranslateCache(&CPUInfo._L2); -	TranslateCache(&CPUInfo._L3); -} - -// CProcessor::CProcessor -// ====================== -// Class constructor: -///////////////////////// -CProcessor::CProcessor() -{ -	uqwFrequency = 0; -	strCPUName[0] = 0; -	memset(&CPUInfo, 0, sizeof(CPUInfo)); -} - -// unsigned __int64 CProcessor::GetCPUFrequency(unsigned int uiMeasureMSecs) -// ========================================================================= -// Function to query the current CPU frequency -//////////////////////////////////////////////////////////////////////////// -F64 CProcessor::GetCPUFrequency(unsigned int /*uiMeasureMSecs*/) -{ -	U64 frequency = 0; -	size_t len = sizeof(frequency); -	 -	if(sysctlbyname("hw.cpufrequency", &frequency, &len, NULL, 0) == 0) -	{ -		uqwFrequency = (F64)frequency; -	} -	 -	return uqwFrequency; -} - -static bool hasFeature(const char *name) -{ -	bool result = false; -	int val = 0; -	size_t len = sizeof(val); -	 -	if(sysctlbyname(name, &val, &len, NULL, 0) == 0) -	{ -		if(val != 0) -			result = true; -	} -	 -	return result; -} - -// const ProcessorInfo *CProcessor::GetCPUInfo() -// ============================================= -// Calls all the other detection function to create an detailed -// processor information -/////////////////////////////////////////////////////////////// -const ProcessorInfo *CProcessor::GetCPUInfo() -{ -	int pagesize = 0; -	int cachelinesize = 0; -	int l1icachesize = 0; -	int l1dcachesize = 0; -	int l2settings = 0; -	int l2cachesize = 0; -	int l3settings = 0; -	int l3cachesize = 0; -	int ncpu = 0; -	int cpusubtype = 0; -	 -	// sysctl knows all. -	int mib[2]; -	size_t len; -	mib[0] = CTL_HW; -	 -	mib[1] = HW_PAGESIZE; -	len = sizeof(pagesize); -	sysctl(mib, 2, &pagesize, &len, NULL, 0); - -	mib[1] = HW_CACHELINE; -	len = sizeof(cachelinesize); -	sysctl(mib, 2, &cachelinesize, &len, NULL, 0); -	 -	mib[1] = HW_L1ICACHESIZE; -	len = sizeof(l1icachesize); -	sysctl(mib, 2, &l1icachesize, &len, NULL, 0); -	 -	mib[1] = HW_L1DCACHESIZE; -	len = sizeof(l1dcachesize); -	sysctl(mib, 2, &l1dcachesize, &len, NULL, 0); -	 -	mib[1] = HW_L2SETTINGS; -	len = sizeof(l2settings); -	sysctl(mib, 2, &l2settings, &len, NULL, 0); -	 -	mib[1] = HW_L2CACHESIZE; -	len = sizeof(l2cachesize); -	sysctl(mib, 2, &l2cachesize, &len, NULL, 0); -	 -	mib[1] = HW_L3SETTINGS; -	len = sizeof(l3settings); -	sysctl(mib, 2, &l3settings, &len, NULL, 0); -	 -	mib[1] = HW_L3CACHESIZE; -	len = sizeof(l3cachesize); -	sysctl(mib, 2, &l3cachesize, &len, NULL, 0); -	 -	mib[1] = HW_NCPU; -	len = sizeof(ncpu); -	sysctl(mib, 2, &ncpu, &len, NULL, 0); -	 -	sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0); -	 -	strCPUName[0] = 0; -	 -	if((ncpu == 0) || (ncpu == 1)) -	{ -		// Uhhh... -	} -	else if(ncpu == 2) -	{ -		strncat(strCPUName, "Dual ", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -	} -	else -	{ -		snprintf(strCPUName, sizeof(strCPUName), "%d x ", ncpu);	/* Flawfinder: ignore */ -	} -	 -#if __ppc__ -	switch(cpusubtype) -	{ -		case CPU_SUBTYPE_POWERPC_601://         ((cpu_subtype_t) 1) -			strncat(strCPUName, "PowerPC 601", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -			 -		break; -		case CPU_SUBTYPE_POWERPC_602://         ((cpu_subtype_t) 2) -			strncat(strCPUName, "PowerPC 602", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_603://         ((cpu_subtype_t) 3) -			strncat(strCPUName, "PowerPC 603", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_603e://        ((cpu_subtype_t) 4) -			strncat(strCPUName, "PowerPC 603e", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_603ev://       ((cpu_subtype_t) 5) -			strncat(strCPUName, "PowerPC 603ev", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_604://         ((cpu_subtype_t) 6) -			strncat(strCPUName, "PowerPC 604", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_604e://        ((cpu_subtype_t) 7) -			strncat(strCPUName, "PowerPC 604e", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_620://			((cpu_subtype_t) 8) -			strncat(strCPUName, "PowerPC 620", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_750://         ((cpu_subtype_t) 9) -			strncat(strCPUName, "PowerPC 750", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC G3", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_7400://        ((cpu_subtype_t) 10) -			strncat(strCPUName, "PowerPC 7400", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_7450://        ((cpu_subtype_t) 11) -			strncat(strCPUName, "PowerPC 7450", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC G4", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; -		case CPU_SUBTYPE_POWERPC_970://         ((cpu_subtype_t) 100) -			strncat(strCPUName, "PowerPC 970", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -			strncat(CPUInfo.strFamily, "PowerPC G5", sizeof(CPUInfo.strFamily)-strlen(CPUInfo.strFamily)-1);	/* Flawfinder: ignore */ -		break; - -		default: -			strncat(strCPUName, "PowerPC (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */ -		break; -	} - -	CPUInfo._Ext.EMMX_MultimediaExtensions =  -	CPUInfo._Ext.MMX_MultimediaExtensions =  -	CPUInfo._Ext.SSE_StreamingSIMD_Extensions = -	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = false; - -	CPUInfo._Ext.Altivec_Extensions = hasFeature("hw.optional.altivec"); - -#endif - -#if __i386__ -	// MBW -- XXX -- TODO -- make this call AnalyzeIntelProcessor()? -	switch(cpusubtype) -	{ -		default: -			strncat(strCPUName, "i386 (Unknown)", sizeof(strCPUName)-strlen(strCPUName)-1);	/* Flawfinder: ignore */	 -		break; -	} - -	CPUInfo._Ext.EMMX_MultimediaExtensions = hasFeature("hw.optional.mmx");  // MBW -- XXX -- this may be wrong... -	CPUInfo._Ext.MMX_MultimediaExtensions = hasFeature("hw.optional.mmx"); -	CPUInfo._Ext.SSE_StreamingSIMD_Extensions = hasFeature("hw.optional.sse"); -	CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions = hasFeature("hw.optional.sse2"); -	CPUInfo._Ext.Altivec_Extensions = false; -	CPUInfo._Ext.AA64_AMD64BitArchitecture = hasFeature("hw.optional.x86_64"); - -#endif - -	// Terse CPU info uses this string... -	strncpy(CPUInfo.strBrandID, strCPUName,sizeof(CPUInfo.strBrandID)-1);	/* Flawfinder: ignore */	 -	CPUInfo.strBrandID[sizeof(CPUInfo.strBrandID)-1]='\0'; -	 -	// Fun cache config stuff... -	 -	if(l1dcachesize != 0) -	{ -		CPUInfo._L1.Data.bPresent = true; -		snprintf(CPUInfo._L1.Data.strSize, sizeof(CPUInfo._L1.Data.strSize), "%d KB", l1dcachesize / 1024);	/* Flawfinder: ignore */ -//		CPUInfo._L1.Data.uiAssociativeWays = ???; -		CPUInfo._L1.Data.uiLineSize = cachelinesize; +		// *NOTE:Mani - This is for linux only. +		LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); +		if(cpuinfo) +		{ +			char line[MAX_STRING]; +			memset(line, 0, MAX_STRING); +			while(fgets(line, MAX_STRING, cpuinfo)) +			{ +				line[strlen(line)-1] = ' '; +				s << line; +				s << std::endl; +			} +			fclose(cpuinfo); +			s << std::endl; +		} +		else +		{ +			s << "Unable to collect processor information" << std::endl; +		} +		return s.str();  	} +		 +}; -	if(l1icachesize != 0) -	{ -		CPUInfo._L1.Instruction.bPresent = true; -		snprintf(CPUInfo._L1.Instruction.strSize, sizeof(CPUInfo._L1.Instruction.strSize), "%d KB", l1icachesize / 1024);	/* Flawfinder: ignore */ -//		CPUInfo._L1.Instruction.uiAssociativeWays = ???; -		CPUInfo._L1.Instruction.uiLineSize = cachelinesize; -	} -	if(l2cachesize != 0) -	{ -		CPUInfo._L2.bPresent = true; -		snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l2cachesize / 1024);	/* Flawfinder: ignore */ -//		CPUInfo._L2.uiAssociativeWays = ???; -		CPUInfo._L2.uiLineSize = cachelinesize; -	} +#endif // LL_MSVC elif LL_DARWIN elif LL_LINUX -	if(l3cachesize != 0) -	{ -		CPUInfo._L2.bPresent = true; -		snprintf(CPUInfo._L2.strSize, sizeof(CPUInfo._L2.strSize), "%d KB", l3cachesize / 1024);	/* Flawfinder: ignore */ -//		CPUInfo._L2.uiAssociativeWays = ???; -		CPUInfo._L2.uiLineSize = cachelinesize; +////////////////////////////////////////////////////// +// Interface definition +LLProcessorInfo::LLProcessorInfo() : mImpl(NULL) +{ +	// *NOTE:Mani - not thread safe. +	if(!mImpl) +	{ +#ifdef LL_MSVC +		static LLProcessorInfoWindowsImpl the_impl;  +		mImpl = &the_impl; +#elif LL_DARWIN +		static LLProcessorInfoDarwinImpl the_impl;  +		mImpl = &the_impl; +#else +		static LLProcessorInfoLinuxImpl the_impl;  +		mImpl = &the_impl;		 +#endif // LL_MSVC  	} -	 -	CPUInfo._Ext.FPU_FloatingPointUnit = hasFeature("hw.optional.floatingpoint"); - -//	printf("pagesize = 0x%x\n", pagesize); -//	printf("cachelinesize = 0x%x\n", cachelinesize); -//	printf("l1icachesize = 0x%x\n", l1icachesize); -//	printf("l1dcachesize = 0x%x\n", l1dcachesize); -//	printf("l2settings = 0x%x\n", l2settings); -//	printf("l2cachesize = 0x%x\n", l2cachesize); -//	printf("l3settings = 0x%x\n", l3settings); -//	printf("l3cachesize = 0x%x\n", l3cachesize); -	 -	// After reading we translate the configuration to strings -	TranslateProcessorConfiguration(); - -	// After all we return the class CPUInfo member var -	return (&CPUInfo);  } -#endif // LL_DARWIN -// bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -// ====================================================================== -// Gets the frequency and processor information and writes it to a string -///////////////////////////////////////////////////////////////////////// -bool CProcessor::CPUInfoToText(char *strBuffer, unsigned int uiMaxLen) -{ -#define LENCHECK                len = (unsigned int) strlen(buf); if (len >= uiMaxLen) return false; strcpy(strBuffer, buf); strBuffer += len;     /*Flawfinder: ignore*/ -#define COPYADD(str)            strcpy(buf, str); LENCHECK;    /* Flawfinder: ignore */ -#define FORMATADD(format, var)  sprintf(buf, format, var); LENCHECK;    /* Flawfinder: ignore */ -#define BOOLADD(str, boolvar)   COPYADD(str); if (boolvar) { COPYADD(" Yes\n"); } else { COPYADD(" No\n"); } - -	char buf[1024];	/* Flawfinder: ignore */	 -	unsigned int len; - -	// First we have to get the frequency -    GetCPUFrequency(50); - -	// Then we get the processor information -	GetCPUInfo(); - -    // Now we construct the string (see the macros at function beginning) -	strBuffer[0] = 0; - -	COPYADD("// CPU General Information\n//////////////////////////\n"); -	FORMATADD("Processor name:   %s\n", strCPUName); -	FORMATADD("Frequency:        %.2f MHz\n\n", (float) uqwFrequency / 1000000.0f); -	FORMATADD("Vendor:           %s\n", CPUInfo.strVendor); -	FORMATADD("Family:           %s\n", CPUInfo.strFamily); -	FORMATADD("Extended family:  %d\n", CPUInfo.uiExtendedFamily); -	FORMATADD("Model:            %s\n", CPUInfo.strModel); -	FORMATADD("Extended model:   %d\n", CPUInfo.uiExtendedModel); -	FORMATADD("Type:             %s\n", CPUInfo.strType); -	FORMATADD("Brand ID:         %s\n", CPUInfo.strBrandID); -	if (CPUInfo._Ext.PN_ProcessorSerialNumber) -	{ -		FORMATADD("Processor Serial: %s\n", CPUInfo.strProcessorSerial); -	} -	else -	{ -	  COPYADD("Processor Serial: Disabled\n"); -	} -#if !LL_SOLARIS		//  NOTE: Why bother printing all this when it's irrelavent - -	COPYADD("\n\n// CPU Configuration\n////////////////////\n"); -	FORMATADD("L1 instruction cache:           %s\n", CPUInfo._L1.Instruction.strCache); -	FORMATADD("L1 data cache:                  %s\n", CPUInfo._L1.Data.strCache); -	FORMATADD("L2 cache:                       %s\n", CPUInfo._L2.strCache); -	FORMATADD("L3 cache:                       %s\n", CPUInfo._L3.strCache); -	FORMATADD("Trace cache:                    %s\n", CPUInfo._Trace.strCache); -	FORMATADD("Instruction TLB:                %s\n", CPUInfo._Instruction.strTLB); -	FORMATADD("Data TLB:                       %s\n", CPUInfo._Data.strTLB); -	FORMATADD("Max Supported CPUID-Level:      0x%08lX\n", CPUInfo.MaxSupportedLevel); -	FORMATADD("Max Supported Ext. CPUID-Level: 0x%08lX\n", CPUInfo.MaxSupportedExtendedLevel); - -	COPYADD("\n\n// CPU Extensions\n/////////////////\n"); -	BOOLADD("AA64   AMD 64-bit Architecture:                    ", CPUInfo._Ext.AA64_AMD64BitArchitecture); -	BOOLADD("ACPI   Thermal Monitor And Clock Control:          ", CPUInfo._Ext.ACPI_ThermalMonitorAndClockControl); -	BOOLADD("APIC   Advanced Programmable Interrupt Controller: ", CPUInfo._Ext.APIC_AdvancedProgrammableInterruptController); -	FORMATADD("       APIC-ID:                                     %d\n", CPUInfo._Ext.APIC_ID); -	BOOLADD("CLFSH  CLFLUSH Instruction Presence:               ", CPUInfo._Ext.CLFSH_CFLUSH_Instruction); -	FORMATADD("       CLFLUSH Instruction Cache Line Size:         %d\n", CPUInfo._Ext.CLFLUSH_InstructionCacheLineSize); -	BOOLADD("CMOV   Conditional Move And Compare Instructions:  ", CPUInfo._Ext.CMOV_ConditionalMoveAndCompareInstructions); -	BOOLADD("CX8    COMPXCHG8B Instruction:                     ", CPUInfo._Ext.CX8_COMPXCHG8B_Instruction); -	BOOLADD("DE     Debugging Extensions:                       ", CPUInfo._Ext.DE_DebuggingExtensions); -	BOOLADD("DS     Debug Store:                                ", CPUInfo._Ext.DS_DebugStore); -	BOOLADD("FGPAT  Page Attribute Table:                       ", CPUInfo._Ext.FGPAT_PageAttributeTable); -	BOOLADD("FPU    Floating Point Unit:                        ", CPUInfo._Ext.FPU_FloatingPointUnit); -	BOOLADD("FXSR   Fast Streaming SIMD Extensions Save/Restore:", CPUInfo._Ext.FXSR_FastStreamingSIMD_ExtensionsSaveRestore); -	BOOLADD("HT     Hyper Threading:                            ", CPUInfo._Ext.HT_HyperThreading); -	BOOLADD("IA64   Intel 64-Bit Architecture:                  ", CPUInfo._Ext.IA64_Intel64BitArchitecture); -	BOOLADD("MCA    Machine Check Architecture:                 ", CPUInfo._Ext.MCA_MachineCheckArchitecture); -	BOOLADD("MCE    Machine Check Exception:                    ", CPUInfo._Ext.MCE_MachineCheckException); -	BOOLADD("MMX    Multimedia Extensions:                      ", CPUInfo._Ext.MMX_MultimediaExtensions); -	BOOLADD("MMX+   Multimedia Extensions:                      ", CPUInfo._Ext.EMMX_MultimediaExtensions); -	BOOLADD("MSR    Model Specific Registers:                   ", CPUInfo._Ext.MSR_ModelSpecificRegisters); -	BOOLADD("MTRR   Memory Type Range Registers:                ", CPUInfo._Ext.MTRR_MemoryTypeRangeRegisters); -	BOOLADD("PAE    Physical Address Extension:                 ", CPUInfo._Ext.PAE_PhysicalAddressExtension); -	BOOLADD("PGE    PTE Global Flag:                            ", CPUInfo._Ext.PGE_PTE_GlobalFlag); -	if (CPUInfo._Ext.PN_ProcessorSerialNumber) -	{ -		FORMATADD("PN     Processor Serial Number:                     %s\n", CPUInfo.strProcessorSerial); -	} -	else -	{ -		COPYADD("PN     Processor Serial Number:                     Disabled\n"); -	} -	BOOLADD("PSE    Page Size Extensions:                       ", CPUInfo._Ext.PSE_PageSizeExtensions); -	BOOLADD("PSE36  36-bit Page Size Extension:                 ", CPUInfo._Ext.PSE36_36bitPageSizeExtension); -	BOOLADD("SEP    Fast System Call:                           ", CPUInfo._Ext.SEP_FastSystemCall); -	BOOLADD("SS     Self Snoop:                                 ", CPUInfo._Ext.SS_SelfSnoop); -	BOOLADD("SSE    Streaming SIMD Extensions:                  ", CPUInfo._Ext.SSE_StreamingSIMD_Extensions); -	BOOLADD("SSE2   Streaming SIMD 2 Extensions:                ", CPUInfo._Ext.SSE2_StreamingSIMD2_Extensions); -	BOOLADD("ALTVEC Altivec Extensions:                         ", CPUInfo._Ext.Altivec_Extensions); -	BOOLADD("TM     Thermal Monitor:                            ", CPUInfo._Ext.TM_ThermalMonitor); -	BOOLADD("TSC    Time Stamp Counter:                         ", CPUInfo._Ext.TSC_TimeStampCounter); -	BOOLADD("VME    Virtual 8086 Mode Enhancements:             ", CPUInfo._Ext.VME_Virtual8086ModeEnhancements); -	BOOLADD("3DNow! Instructions:                               ", CPUInfo._Ext._3DNOW_InstructionExtensions); -	BOOLADD("Enhanced 3DNow! Instructions:                      ", CPUInfo._Ext._E3DNOW_InstructionExtensions); -#endif -	// Yippie!!! -	return true; -} +LLProcessorInfo::~LLProcessorInfo() {} +F64 LLProcessorInfo::getCPUFrequency() const { return mImpl->getCPUFrequency(); } +bool LLProcessorInfo::hasSSE() const { return mImpl->hasSSE(); } +bool LLProcessorInfo::hasSSE2() const { return mImpl->hasSSE2(); } +bool LLProcessorInfo::hasAltivec() const { return mImpl->hasAltivec(); } +std::string LLProcessorInfo::getCPUFamilyName() const { return mImpl->getCPUFamilyName(); } +std::string LLProcessorInfo::getCPUBrandName() const { return mImpl->getCPUBrandName(); } +std::string LLProcessorInfo::getCPUFeatureDescription() const { return mImpl->getCPUFeatureDescription(); } -// bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -// =========================================================== -// Takes use of CProcessor::CPUInfoToText and saves the string to a -// file -/////////////////////////////////////////////////////////////////// -bool CProcessor::WriteInfoTextFile(const std::string& strFilename) -{ -	char buf[16384];	/* Flawfinder: ignore */	 - -	// First we get the string -	if (!CPUInfoToText(buf, 16383)) -		return false; - -	// Then we create a new file (CREATE_ALWAYS) -	LLFILE *file = LLFile::fopen(strFilename, "w");	/* Flawfinder: ignore */	 -	if (!file) -		return false; - -	// After that we write the string to the file -	unsigned long dwBytesToWrite, dwBytesWritten; -	dwBytesToWrite = (unsigned long) strlen(buf);	 /*Flawfinder: ignore*/ -	dwBytesWritten = (unsigned long) fwrite(buf, 1, dwBytesToWrite, file); -	fclose(file); -	if (dwBytesToWrite != dwBytesWritten) -		return false; - -	// Done -	return true; -} diff --git a/indra/llcommon/llprocessor.h b/indra/llcommon/llprocessor.h index 746d007a7f..fc2c8dacfb 100644 --- a/indra/llcommon/llprocessor.h +++ b/indra/llcommon/llprocessor.h @@ -30,167 +30,26 @@   * $/LicenseInfo$   */ -// Author: Benjamin Jurke -// File history: 27.02.2002   File created. -/////////////////////////////////////////// -  #ifndef LLPROCESSOR_H  #define LLPROCESSOR_H +class LLProcessorInfoImpl; -// Options: -/////////// -#if LL_WINDOWS -#define PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -#endif - -#if LL_MSVC && _M_X64 -#      define LL_X86_64 1 -#      define LL_X86 1 -#elif LL_MSVC && _M_IX86 -#      define LL_X86 1 -#elif LL_GNUC && ( defined(__amd64__) || defined(__x86_64__) ) -#      define LL_X86_64 1 -#      define LL_X86 1 -#elif LL_GNUC && ( defined(__i386__) ) -#      define LL_X86 1 -#elif LL_GNUC && ( defined(__powerpc__) || defined(__ppc__) ) -#      define LL_PPC 1 -#endif - - -struct ProcessorExtensions -{ -	bool FPU_FloatingPointUnit; -	bool VME_Virtual8086ModeEnhancements; -	bool DE_DebuggingExtensions; -	bool PSE_PageSizeExtensions; -	bool TSC_TimeStampCounter; -	bool MSR_ModelSpecificRegisters; -	bool PAE_PhysicalAddressExtension; -	bool MCE_MachineCheckException; -	bool CX8_COMPXCHG8B_Instruction; -	bool APIC_AdvancedProgrammableInterruptController; -	unsigned int APIC_ID; -	bool SEP_FastSystemCall; -	bool MTRR_MemoryTypeRangeRegisters; -	bool PGE_PTE_GlobalFlag; -	bool MCA_MachineCheckArchitecture; -	bool CMOV_ConditionalMoveAndCompareInstructions; -	bool FGPAT_PageAttributeTable; -	bool PSE36_36bitPageSizeExtension; -	bool PN_ProcessorSerialNumber; -	bool CLFSH_CFLUSH_Instruction; -	unsigned int CLFLUSH_InstructionCacheLineSize; -	bool DS_DebugStore; -	bool ACPI_ThermalMonitorAndClockControl; -	bool EMMX_MultimediaExtensions; -	bool MMX_MultimediaExtensions; -	bool FXSR_FastStreamingSIMD_ExtensionsSaveRestore; -	bool SSE_StreamingSIMD_Extensions; -	bool SSE2_StreamingSIMD2_Extensions; -	bool Altivec_Extensions; -	bool SS_SelfSnoop; -	bool HT_HyperThreading; -	unsigned int HT_HyterThreadingSiblings; -	bool TM_ThermalMonitor; -	bool IA64_Intel64BitArchitecture; -	bool _3DNOW_InstructionExtensions; -	bool _E3DNOW_InstructionExtensions; -	bool AA64_AMD64BitArchitecture; -}; - -struct ProcessorCache -{ -	bool bPresent; -	char strSize[32];	/* Flawfinder: ignore */	 -	unsigned int uiAssociativeWays; -	unsigned int uiLineSize; -	bool bSectored; -	char strCache[128];	/* Flawfinder: ignore */	 -}; - -struct ProcessorL1Cache -{ -    ProcessorCache Instruction; -	ProcessorCache Data; -}; - -struct ProcessorTLB +class LL_COMMON_API LLProcessorInfo  { -	bool bPresent; -	char strPageSize[32];	/* Flawfinder: ignore */	 -	unsigned int uiAssociativeWays; -	unsigned int uiEntries; -	char strTLB[128];	/* Flawfinder: ignore */	 -}; - -struct ProcessorInfo -{ -	char strVendor[16];	/* Flawfinder: ignore */	 -	unsigned int uiFamily; -	unsigned int uiExtendedFamily; -	char strFamily[64];	/* Flawfinder: ignore */	 -	unsigned int uiModel; -	unsigned int uiExtendedModel; -	char strModel[128];	/* Flawfinder: ignore */	 -	unsigned int uiStepping; -	unsigned int uiType; -	char strType[64];	/* Flawfinder: ignore */	 -	unsigned int uiBrandID; -	char strBrandID[64];	/* Flawfinder: ignore */	 -	char strProcessorSerial[64];	/* Flawfinder: ignore */	 -	unsigned long MaxSupportedLevel; -	unsigned long MaxSupportedExtendedLevel; -	ProcessorExtensions _Ext; -	ProcessorL1Cache _L1; -	ProcessorCache _L2; -	ProcessorCache _L3; -	ProcessorCache _Trace; -	ProcessorTLB _Instruction; -	ProcessorTLB _Data; -}; - - -// CProcessor -// ========== -// Class for detecting the processor name, type and available -// extensions as long as it's speed. -///////////////////////////////////////////////////////////// -class CProcessor -{ -// Constructor / Destructor: -////////////////////////////  public: -	CProcessor(); - -// Private vars: -//////////////// -public: -	F64 uqwFrequency; -	char strCPUName[128];	/* Flawfinder: ignore */	 -	ProcessorInfo CPUInfo; - -// Private functions: -///////////////////// +	LLProcessorInfo();  + 	~LLProcessorInfo(); + +	F64 getCPUFrequency() const; +	bool hasSSE() const; +	bool hasSSE2() const; +	bool hasAltivec() const; +	std::string getCPUFamilyName() const; +	std::string getCPUBrandName() const; +	std::string getCPUFeatureDescription() const;  private: -	bool AnalyzeIntelProcessor(); -	bool AnalyzeAMDProcessor(); -	bool AnalyzeUnknownProcessor(); -	bool CheckCPUIDPresence(); -	void DecodeProcessorConfiguration(unsigned int cfg); -	void TranslateProcessorConfiguration(); -	void GetStandardProcessorConfiguration(); -	void GetStandardProcessorExtensions(); - -// Public functions: -//////////////////// -public: -	F64 GetCPUFrequency(unsigned int uiMeasureMSecs); -	const ProcessorInfo *GetCPUInfo(); -	bool CPUInfoToText(char *strBuffer, unsigned int uiMaxLen); -	bool WriteInfoTextFile(const std::string& strFilename); +	LLProcessorInfoImpl* mImpl;  }; - -#endif +#endif // LLPROCESSOR_H diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 52b1b63209..d41d0c8a3f 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -58,7 +58,6 @@  #	include <unistd.h>  #	include <sys/sysinfo.h>  const char MEMINFO_FILE[] = "/proc/meminfo"; -const char CPUINFO_FILE[] = "/proc/cpuinfo";  #elif LL_SOLARIS  #	include <stdio.h>  #	include <unistd.h> @@ -513,71 +512,21 @@ U32 LLOSInfo::getProcessResidentSizeKB()  LLCPUInfo::LLCPUInfo()  {  	std::ostringstream out; -	CProcessor proc; -	const ProcessorInfo* info = proc.GetCPUInfo(); +	LLProcessorInfo proc;  	// proc.WriteInfoTextFile("procInfo.txt"); -	mHasSSE = info->_Ext.SSE_StreamingSIMD_Extensions; -	mHasSSE2 = info->_Ext.SSE2_StreamingSIMD2_Extensions; -	mHasAltivec = info->_Ext.Altivec_Extensions; -	mCPUMHz = (F64)(proc.GetCPUFrequency(50)/1000000.0F); -	mFamily.assign( info->strFamily ); +	mHasSSE = proc.hasSSE(); +	mHasSSE2 = proc.hasSSE2(); +	mHasAltivec = proc.hasAltivec(); +	mCPUMHz = (F64)proc.getCPUFrequency(); +	mFamily = proc.getCPUFamilyName();  	mCPUString = "Unknown"; -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS -	out << proc.strCPUName; +	out << proc.getCPUBrandName();  	if (200 < mCPUMHz && mCPUMHz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check  	{  		out << " (" << mCPUMHz << " MHz)";  	}  	mCPUString = out.str(); -	 -#elif LL_LINUX -	std::map< std::string, std::string > cpuinfo; -	LLFILE* cpuinfo_fp = LLFile::fopen(CPUINFO_FILE, "rb"); -	if(cpuinfo_fp) -	{ -		char line[MAX_STRING]; -		memset(line, 0, MAX_STRING); -		while(fgets(line, MAX_STRING, cpuinfo_fp)) -		{ -			// /proc/cpuinfo on Linux looks like: -			// name\t*: value\n -			char* tabspot = strchr( line, '\t' ); -			if (tabspot == NULL) -				continue; -			char* colspot = strchr( tabspot, ':' ); -			if (colspot == NULL) -				continue; -			char* spacespot = strchr( colspot, ' ' ); -			if (spacespot == NULL) -				continue; -			char* nlspot = strchr( line, '\n' ); -			if (nlspot == NULL) -				nlspot = line + strlen( line ); // Fallback to terminating NUL -			std::string linename( line, tabspot ); -			std::string llinename(linename); -			LLStringUtil::toLower(llinename); -			std::string lineval( spacespot + 1, nlspot ); -			cpuinfo[ llinename ] = lineval; -		} -		fclose(cpuinfo_fp); -	} -# if LL_X86 -	std::string flags = " " + cpuinfo["flags"] + " "; -	LLStringUtil::toLower(flags); -	mHasSSE = ( flags.find( " sse " ) != std::string::npos ); -	mHasSSE2 = ( flags.find( " sse2 " ) != std::string::npos ); -	 -	F64 mhz; -	if (LLStringUtil::convertToF64(cpuinfo["cpu mhz"], mhz) -	    && 200.0 < mhz && mhz < 10000.0) -	{ -		mCPUMHz = (F64)(mhz); -	} -	if (!cpuinfo["model name"].empty()) -		mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX  }  bool LLCPUInfo::hasAltivec() const @@ -607,38 +556,9 @@ std::string LLCPUInfo::getCPUString() const  void LLCPUInfo::stream(std::ostream& s) const  { -#if LL_WINDOWS || LL_DARWIN || LL_SOLARIS  	// gather machine information. -	char proc_buf[CPUINFO_BUFFER_SIZE];		/* Flawfinder: ignore */ -	CProcessor proc; -	if(proc.CPUInfoToText(proc_buf, CPUINFO_BUFFER_SIZE)) -	{ -		s << proc_buf; -	} -	else -	{ -		s << "Unable to collect processor information" << std::endl; -	} -#else -	// *NOTE: This works on linux. What will it do on other systems? -	LLFILE* cpuinfo = LLFile::fopen(CPUINFO_FILE, "rb"); -	if(cpuinfo) -	{ -		char line[MAX_STRING]; -		memset(line, 0, MAX_STRING); -		while(fgets(line, MAX_STRING, cpuinfo)) -		{ -			line[strlen(line)-1] = ' '; -			s << line; -		} -		fclose(cpuinfo); -		s << std::endl; -	} -	else -	{ -		s << "Unable to collect processor information" << std::endl; -	} -#endif +	s << LLProcessorInfo().getCPUFeatureDescription(); +  	// These are interesting as they reflect our internal view of the  	// CPU's attributes regardless of platform  	s << "->mHasSSE:     " << (U32)mHasSSE << std::endl; diff --git a/indra/llcommon/tests/llprocessor_test.cpp b/indra/llcommon/tests/llprocessor_test.cpp new file mode 100644 index 0000000000..a9e312b70b --- /dev/null +++ b/indra/llcommon/tests/llprocessor_test.cpp @@ -0,0 +1,67 @@ +/**  + * @file llprocessor_test.cpp + * @date 2010-06-01 + * + * $LicenseInfo:firstyear=2010&license=viewergpl$ + *  + * Copyright (c) 2010, Linden Research, Inc. + *  + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab.  Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + *  + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + *  + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + *  + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "../test/lltut.h" + +#include "../llprocessor.h" + + +namespace tut +{ +	struct processor +	{ +	}; + +	typedef test_group<processor> processor_t; +	typedef processor_t::object processor_object_t; +	tut::processor_t tut_processor("processor"); + +	template<> template<> +	void processor_object_t::test<1>() +	{ +		set_test_name("LLProcessorInfo regression test"); + +		LLProcessorInfo pi; +		F64 freq =  pi.getCPUFrequency(); +		//bool sse =  pi.hasSSE(); +		//bool sse2 = pi.hasSSE2(); +		//bool alitvec = pi.hasAltivec(); +		std::string family = pi.getCPUFamilyName(); +		std::string brand =  pi.getCPUBrandName(); +		//std::string steam =  pi.getCPUFeatureDescription(); + +		ensure_not_equals("Unknown Brand name", brand, "Unknown");  +		ensure_not_equals("Unknown Family name", family, "Unknown");  +		ensure("Reasonable CPU Frequency > 100 && < 10000", freq > 100 && freq < 10000); +	} +} diff --git a/indra/llui/llaccordionctrl.cpp b/indra/llui/llaccordionctrl.cpp index 6bf1347514..cd23d5cd33 100644 --- a/indra/llui/llaccordionctrl.cpp +++ b/indra/llui/llaccordionctrl.cpp @@ -352,7 +352,7 @@ void LLAccordionCtrl::addCollapsibleCtrl(LLView* view)  	mAccordionTabs.push_back(accordion_tab);  	accordion_tab->setDropDownStateChangedCallback( boost::bind(&LLAccordionCtrl::onCollapseCtrlCloseOpen, this, mAccordionTabs.size() - 1) ); - +	arrange();	  }  void LLAccordionCtrl::removeCollapsibleCtrl(LLView* view) @@ -541,6 +541,8 @@ void LLAccordionCtrl::arrange()  		S32 panel_height = getRect().getHeight() - 2*BORDER_MARGIN; +		if (accordion_tab->getFitParent()) +			panel_height = accordion_tab->getRect().getHeight();  		ctrlSetLeftTopAndSize(accordion_tab,panel_rect.mLeft,panel_top,panel_width,panel_height);  		show_hide_scrollbar(getRect().getWidth(),getRect().getHeight()); diff --git a/indra/llui/llaccordionctrltab.h b/indra/llui/llaccordionctrltab.h index 82e0234bfc..480b26e130 100644 --- a/indra/llui/llaccordionctrltab.h +++ b/indra/llui/llaccordionctrltab.h @@ -190,6 +190,7 @@ public:  	void showAndFocusHeader();  	void setFitPanel( bool fit ) { mFitPanel = true; } +	bool getFitParent() const { return mFitPanel; }  protected:  	void adjustContainerPanel	(const LLRect& child_rect); diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp index 45f9de8e8d..c93ca1af88 100644 --- a/indra/llui/lllineeditor.cpp +++ b/indra/llui/lllineeditor.cpp @@ -377,7 +377,10 @@ void LLLineEditor::setText(const LLStringExplicit &new_text)  	setCursor(llmin((S32)mText.length(), getCursor()));  	// Set current history line to end of history. -	mCurrentHistoryLine = mLineHistory.end() - 1; +	if(mLineHistory.end() != mLineHistory.begin()) +	{ +		mCurrentHistoryLine = mLineHistory.end() - 1; +	}  	mPrevText = mText;  } diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml index b0211dd85b..d4aebe6cb1 100644 --- a/indra/newview/app_settings/settings.xml +++ b/indra/newview/app_settings/settings.xml @@ -11428,5 +11428,16 @@        <key>Value</key>        <integer>180</integer>      </map> +    <key>HeightUnits</key> +    <map> +      <key>Comment</key> +      <string>Determines which metric units are used: 1(TRUE) for meter and 0(FALSE) for foot.</string> +      <key>Persist</key> +      <integer>1</integer> +      <key>Type</key> +      <string>Boolean</string> +      <key>Value</key> +      <integer>1</integer> +    </map>  </map>  </llsd> diff --git a/indra/newview/llagentwearables.cpp b/indra/newview/llagentwearables.cpp index acf43dda1e..342f9a5d80 100644 --- a/indra/newview/llagentwearables.cpp +++ b/indra/newview/llagentwearables.cpp @@ -2006,6 +2006,8 @@ bool LLAgentWearables::moveWearable(const LLViewerInventoryItem* item, bool clos  // static  void LLAgentWearables::createWearable(LLWearableType::EType type, bool wear, const LLUUID& parent_id)  { +	if (type == LLWearableType::WT_INVALID || type == LLWearableType::WT_NONE) return; +  	LLWearable* wearable = LLWearableList::instance().createNewWearable(type);  	LLAssetType::EType asset_type = wearable->getAssetType();  	LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE; diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 95084666bb..82bd59d25c 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -331,10 +331,6 @@ const char *VFS_INDEX_FILE_BASE = "index.db2.x.";  static std::string gWindowTitle; -std::string gLoginPage; -std::vector<std::string> gLoginURIs; -static std::string gHelperURI; -  LLAppViewer::LLUpdaterInfo *LLAppViewer::sUpdaterInfo = NULL ;  void idle_afk_check() diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp index 01d6c3a8d5..2dafe295fe 100644 --- a/indra/newview/llavataractions.cpp +++ b/indra/newview/llavataractions.cpp @@ -656,6 +656,8 @@ void LLAvatarActions::shareWithAvatars()  	LLFloaterAvatarPicker* picker =  		LLFloaterAvatarPicker::show(boost::bind(give_inventory, _1, _2), TRUE, FALSE);  	picker->setOkBtnEnableCb(boost::bind(is_give_inventory_acceptable)); +	picker->openFriendsTab(); +	LLNotificationsUtil::add("ShareNotification");  }  // static diff --git a/indra/newview/llcofwearables.cpp b/indra/newview/llcofwearables.cpp index 916d53da3c..611396b0e5 100644 --- a/indra/newview/llcofwearables.cpp +++ b/indra/newview/llcofwearables.cpp @@ -58,13 +58,19 @@ static const LLWearableItemNameComparator WEARABLE_NAME_COMPARATOR;  class CofContextMenu : public LLListContextMenu  {  protected: -	static void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id) +	CofContextMenu(LLCOFWearables* cof_wearables) +	:	mCOFWearables(cof_wearables) +	{ +		llassert(mCOFWearables); +	} + +	void updateCreateWearableLabel(LLMenuGL* menu, const LLUUID& item_id)  	{  		LLMenuItemGL* menu_item = menu->getChild<LLMenuItemGL>("create_new"); +		LLWearableType::EType w_type = getWearableType(item_id);  		// Hide the "Create new <WEARABLE_TYPE>" if it's irrelevant. -		LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); -		if (!item || !item->isWearableType()) +		if (w_type == LLWearableType::WT_NONE)  		{  			menu_item->setVisible(FALSE);  			return; @@ -72,25 +78,67 @@ protected:  		// Set proper label for the "Create new <WEARABLE_TYPE>" menu item.  		LLStringUtil::format_map_t args; -		LLWearableType::EType w_type = item->getWearableType();  		args["[WEARABLE_TYPE]"] = LLWearableType::getTypeDefaultNewName(w_type);  		std::string new_label = LLTrans::getString("CreateNewWearable", args);  		menu_item->setLabel(new_label);  	} -	static void createNew(const LLUUID& item_id) +	void createNew(const LLUUID& item_id)  	{ -		LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); -		if (!item || !item->isWearableType()) return; +		LLAgentWearables::createWearable(getWearableType(item_id), true); +	} + +	// Get wearable type of the given item. +	// +	// There is a special case: so-called "dummy items" +	// (i.e. the ones that are there just to indicate that you're not wearing +	// any wearables of the corresponding type. They are currently grayed out +	// and suffixed with "not worn"). +	// Those items don't have an UUID, but they do have an associated wearable type. +	// If the user has invoked context menu for such item, +	// we ignore the passed item_id and retrieve wearable type from the item. +	LLWearableType::EType getWearableType(const LLUUID& item_id) +	{ +		if (!isDummyItem(item_id)) +		{ +			LLViewerInventoryItem* item = gInventory.getLinkedItem(item_id); +			if (item && item->isWearableType()) +			{ +				return item->getWearableType(); +			} +		} +		else if (mCOFWearables) // dummy item selected +		{ +			LLPanelDummyClothingListItem* item; + +			item = dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem()); +			if (item) +			{ +				return item->getWearableType(); +			} +		} + +		return LLWearableType::WT_NONE; +	} -		LLAgentWearables::createWearable(item->getWearableType(), true); +	static bool isDummyItem(const LLUUID& item_id) +	{ +		return item_id.isNull();  	} + +	LLCOFWearables* mCOFWearables;  };  ////////////////////////////////////////////////////////////////////////// -class CofAttachmentContextMenu : public LLListContextMenu +class CofAttachmentContextMenu : public CofContextMenu  { +public: +	CofAttachmentContextMenu(LLCOFWearables* cof_wearables) +	:	CofContextMenu(cof_wearables) +	{ +	} +  protected:  	/*virtual*/ LLContextMenu* createMenu() @@ -108,8 +156,13 @@ protected:  class CofClothingContextMenu : public CofContextMenu  { -protected: +public: +	CofClothingContextMenu(LLCOFWearables* cof_wearables) +	:	CofContextMenu(cof_wearables) +	{ +	} +protected:  	/*virtual*/ LLContextMenu* createMenu()  	{  		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -121,7 +174,7 @@ protected:  		registrar.add("Clothing.MoveUp", boost::bind(moveWearable, selected_id, false));  		registrar.add("Clothing.MoveDown", boost::bind(moveWearable, selected_id, true));  		registrar.add("Clothing.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); -		registrar.add("Clothing.Create", boost::bind(createNew, selected_id)); +		registrar.add("Clothing.Create", boost::bind(&CofClothingContextMenu::createNew, this, selected_id));  		enable_registrar.add("Clothing.OnEnable", boost::bind(&CofClothingContextMenu::onEnable, this, _2)); @@ -171,8 +224,13 @@ protected:  class CofBodyPartContextMenu : public CofContextMenu  { -protected: +public: +	CofBodyPartContextMenu(LLCOFWearables* cof_wearables) +	:	CofContextMenu(cof_wearables) +	{ +	} +protected:  	/*virtual*/ LLContextMenu* createMenu()  	{  		LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar; @@ -184,7 +242,7 @@ protected:  		LLPanelOutfitEdit* panel_oe = dynamic_cast<LLPanelOutfitEdit*>(LLSideTray::getInstance()->getPanel("panel_outfit_edit"));  		registrar.add("BodyPart.Replace", boost::bind(&LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked, panel_oe, selected_id));  		registrar.add("BodyPart.Edit", boost::bind(LLAgentWearables::editWearable, selected_id)); -		registrar.add("BodyPart.Create", boost::bind(createNew, selected_id)); +		registrar.add("BodyPart.Create", boost::bind(&CofBodyPartContextMenu::createNew, this, selected_id));  		enable_registrar.add("BodyPart.OnEnable", boost::bind(&CofBodyPartContextMenu::onEnable, this, _2)); @@ -219,9 +277,9 @@ LLCOFWearables::LLCOFWearables() : LLPanel(),  	mBodyParts(NULL),  	mLastSelectedList(NULL)  { -	mClothingMenu = new CofClothingContextMenu(); -	mAttachmentMenu = new CofAttachmentContextMenu(); -	mBodyPartMenu = new CofBodyPartContextMenu(); +	mClothingMenu = new CofClothingContextMenu(this); +	mAttachmentMenu = new CofAttachmentContextMenu(this); +	mBodyPartMenu = new CofBodyPartContextMenu(this);  };  LLCOFWearables::~LLCOFWearables() diff --git a/indra/newview/llfloateravatarpicker.cpp b/indra/newview/llfloateravatarpicker.cpp index 96364f9418..8f6816b845 100644 --- a/indra/newview/llfloateravatarpicker.cpp +++ b/indra/newview/llfloateravatarpicker.cpp @@ -446,6 +446,19 @@ BOOL LLFloaterAvatarPicker::handleDragAndDrop(S32 x, S32 y, MASK mask,  	return TRUE;  } + +void LLFloaterAvatarPicker::openFriendsTab() +{ +	LLTabContainer* tab_container = getChild<LLTabContainer>("ResidentChooserTabs"); +	if (tab_container == NULL) +	{ +		llassert(tab_container != NULL); +		return; +	} + +	tab_container->selectTabByName("FriendsPanel"); +} +  // static   void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void**)  { diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h index e69b814f9f..0af72e85a0 100644 --- a/indra/newview/llfloateravatarpicker.h +++ b/indra/newview/llfloateravatarpicker.h @@ -66,6 +66,8 @@ public:  						   void *cargo_data, EAcceptance *accept,  						   std::string& tooltip_msg); +	void openFriendsTab(); +  private:  	void editKeystroke(class LLLineEditor* caller, void* user_data); diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp index c259659083..e74bfae026 100644 --- a/indra/newview/llfloatermap.cpp +++ b/indra/newview/llfloatermap.cpp @@ -54,7 +54,10 @@  // Constants  //  const F32 MAP_MINOR_DIR_THRESHOLD = 0.08f; - +const S32 MAP_PADDING_LEFT = 0; +const S32 MAP_PADDING_TOP = 2; +const S32 MAP_PADDING_RIGHT = 2; +const S32 MAP_PADDING_BOTTOM = 0;  //  // Member functions  // @@ -106,7 +109,8 @@ BOOL LLFloaterMap::postBuild()  		mPopupMenu->setItemEnabled ("Stop Tracking", false);  	} -	stretchMiniMap(getRect().getWidth(),getRect().getHeight()); +	stretchMiniMap(getRect().getWidth() - MAP_PADDING_LEFT - MAP_PADDING_RIGHT +		,getRect().getHeight() - MAP_PADDING_TOP - MAP_PADDING_BOTTOM);  	updateMinorDirections(); @@ -238,7 +242,7 @@ void LLFloaterMap::stretchMiniMap(S32 width,S32 height)  	if(mMap)  	{  		LLRect map_rect; -		map_rect.setLeftTopAndSize( 0, getRect().getHeight(), width, height); +		map_rect.setLeftTopAndSize( MAP_PADDING_LEFT, getRect().getHeight() - MAP_PADDING_TOP, width, height);  		mMap->reshape( width, height, 1);  		mMap->setRect(map_rect);  	} @@ -248,7 +252,8 @@ void LLFloaterMap::reshape(S32 width, S32 height, BOOL called_from_parent)  {  	LLFloater::reshape(width, height, called_from_parent); -	stretchMiniMap(width, height); +	stretchMiniMap(width - MAP_PADDING_LEFT - MAP_PADDING_RIGHT +		,height - MAP_PADDING_TOP - MAP_PADDING_BOTTOM);  	updateMinorDirections();  } diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp index 293585cd9c..7ce96a6ac1 100644 --- a/indra/newview/llinventorybridge.cpp +++ b/indra/newview/llinventorybridge.cpp @@ -2209,13 +2209,7 @@ void LLFolderBridge::determineFolderType()  BOOL LLFolderBridge::isItemRenameable() const  { -	LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory(); -	if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) -	   && (cat->getOwnerID() == gAgent.getID())) -	{ -		return TRUE; -	} -	return FALSE; +	return get_is_category_renameable(getInventoryModel(), mUUID);  }  void LLFolderBridge::restoreItem() diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp index ca6cede7e9..c86d463a08 100644 --- a/indra/newview/llinventoryfunctions.cpp +++ b/indra/newview/llinventoryfunctions.cpp @@ -309,6 +309,11 @@ BOOL get_is_category_removable(const LLInventoryModel* model, const LLUUID& id)  BOOL get_is_category_renameable(const LLInventoryModel* model, const LLUUID& id)  { +	if (!model) +	{ +		return FALSE; +	} +  	LLViewerInventoryCategory* cat = model->getCategory(id);  	if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()) && diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp index f1c13de8bb..1beaaf3cb4 100644 --- a/indra/newview/llnearbychat.cpp +++ b/indra/newview/llnearbychat.cpp @@ -49,7 +49,6 @@  #include "llchannelmanager.h"  #include "llagent.h" 			// gAgent -#include "llfloaterscriptdebug.h"  #include "llchathistory.h"  #include "llstylemap.h" @@ -163,25 +162,6 @@ std::string appendTime()  void	LLNearbyChat::addMessage(const LLChat& chat,bool archive,const LLSD &args)  { -	if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) -	{ -		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) -			return; -		if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) -		{ - -			LLColor4 txt_color; - -			LLViewerChat::getChatColor(chat,txt_color); -			 -			LLFloaterScriptDebug::addScriptLine(chat.mText, -												chat.mFromName,  -												txt_color,  -												chat.mFromID); -			return; -		} -	} -  	LLChat& tmp_chat = const_cast<LLChat&>(chat);  	if(tmp_chat.mTimeStr.empty()) diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp index 9824517ed1..4b5e765c4f 100644 --- a/indra/newview/llnearbychathandler.cpp +++ b/indra/newview/llnearbychathandler.cpp @@ -36,6 +36,7 @@  #include "llbottomtray.h"  #include "llchatitemscontainerctrl.h" +#include "llfloaterscriptdebug.h"  #include "llnearbychat.h"  #include "llrecentpeople.h" @@ -287,7 +288,7 @@ void LLNearbyChatScreenChannel::showToastsBottom()  		toast_rect.setLeftTopAndSize(getRect().mLeft , bottom + toast_rect.getHeight(), toast_rect.getWidth() ,toast_rect.getHeight());  		toast->setRect(toast_rect); -		bottom += toast_rect.getHeight() + margin; +		bottom += toast_rect.getHeight() - toast->getTopPad() + margin;  	}  	// use reverse order to provide correct z-order and avoid toast blinking @@ -358,6 +359,29 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg, const LLSD &args)  		//if(tmp_chat.mFromName.empty() && tmp_chat.mFromID!= LLUUID::null)  		//	tmp_chat.mFromName = tmp_chat.mFromID.asString();  	} + +	// don't show toast and add message to chat history on receive debug message +	// with disabled setting showing script errors or enabled setting to show script +	// errors in separate window. +	if (chat_msg.mChatType == CHAT_TYPE_DEBUG_MSG) +	{ +		if(gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) +			return; +		if (gSavedSettings.getS32("ShowScriptErrorsLocation")== 1)// show error in window //("ScriptErrorsAsChat")) +		{ + +			LLColor4 txt_color; + +			LLViewerChat::getChatColor(chat_msg,txt_color); + +			LLFloaterScriptDebug::addScriptLine(chat_msg.mText, +												chat_msg.mFromName, +												txt_color, +												chat_msg.mFromID); +			return; +		} +	} +  	nearby_chat->addMessage(chat_msg, true, args);  	if( nearby_chat->getVisible()  		|| ( chat_msg.mSourceType == CHAT_SOURCE_AGENT diff --git a/indra/newview/llpaneleditwearable.cpp b/indra/newview/llpaneleditwearable.cpp index a1a9300ec2..1aedfec86f 100644 --- a/indra/newview/llpaneleditwearable.cpp +++ b/indra/newview/llpaneleditwearable.cpp @@ -61,6 +61,9 @@  #include "llagentcamera.h"  #include "llmorphview.h" +#include "llcommandhandler.h" +#include "lltextutil.h" +  // register panel with appropriate XML  static LLRegisterPanelClassWrapper<LLPanelEditWearable> t_edit_wearable("panel_edit_wearable"); @@ -608,6 +611,36 @@ LLPanelEditWearable::~LLPanelEditWearable()  } +bool LLPanelEditWearable::changeHeightUnits(const LLSD& new_value) +{ +	updateMetricLayout( new_value.asBoolean() ); +	updateTypeSpecificControls(LLWearableType::WT_SHAPE); +	return true; +} + +void LLPanelEditWearable::updateMetricLayout(BOOL new_value) +{ +	LLUIString current_metric, replacment_metric; +	current_metric = new_value ? mMeters : mFeet; +	replacment_metric = new_value ? mFeet : mMeters; +	mHeigthValue.setArg( "[METRIC1]", current_metric.getString() ); +	mReplacementMetricUrl.setArg( "[URL_METRIC2]", std::string("[secondlife:///app/metricsystem ") + replacment_metric.getString() + std::string("]")); +} + +void LLPanelEditWearable::updateAvatarHeightLabel() +{ +	mTxtAvatarHeight->setText(LLStringUtil::null); +	LLStyle::Params param; +	param.color = mAvatarHeigthLabelColor; +	mTxtAvatarHeight->appendText(mHeigth, false, param); +	param.color = mAvatarHeigthValueLabelColor; +	mTxtAvatarHeight->appendText(mHeigthValue, false, param); +	param.color = mAvatarHeigthLabelColor; // using mAvatarHeigthLabelColor for '/' separator +	mTxtAvatarHeight->appendText(" / ", false, param); +	mTxtAvatarHeight->appendText(this->mReplacementMetricUrl, false, param); +} + +  // virtual   BOOL LLPanelEditWearable::postBuild()  { @@ -700,6 +733,20 @@ BOOL LLPanelEditWearable::postBuild()  		for_each_picker_ctrl_entry <LLTextureCtrl>     (getPanel(type), type, boost::bind(init_texture_ctrl, this, _1, _2));  	} +	// init all strings +	mMeters		= mPanelShape->getString("meters"); +	mFeet		= mPanelShape->getString("feet"); +	mHeigth		= mPanelShape->getString("height") + " "; +	mHeigthValue	= "[HEIGHT] [METRIC1]"; +	mReplacementMetricUrl	= "[URL_METRIC2]"; + +	std::string color = mPanelShape->getString("heigth_label_color"); +	mAvatarHeigthLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); +	color = mPanelShape->getString("heigth_value_label_color"); +	mAvatarHeigthValueLabelColor = LLUIColorTable::instance().getColor(color, LLColor4::green); +	gSavedSettings.getControl("HeightUnits")->getSignal()->connect(boost::bind(&LLPanelEditWearable::changeHeightUnits, this, _2)); +	updateMetricLayout(gSavedSettings.getBOOL("HeightUnits")); +  	return TRUE;  } @@ -1107,12 +1154,22 @@ void LLPanelEditWearable::toggleTypeSpecificControls(LLWearableType::EType type)  void LLPanelEditWearable::updateTypeSpecificControls(LLWearableType::EType type)  { +	const F32 ONE_METER = 1.0; +	const F32 ONE_FOOT = 0.3048 * ONE_METER; // in meters  	// Update controls specific to shape editing panel.  	if (type == LLWearableType::WT_SHAPE)  	{  		// Update avatar height -		std::string avatar_height_str = llformat("%.2f", gAgentAvatarp->mBodySize.mV[VZ]); -		mTxtAvatarHeight->setTextArg("[HEIGHT]", avatar_height_str); +		F32 new_size = gAgentAvatarp->mBodySize.mV[VZ]; +		if (gSavedSettings.getBOOL("HeightUnits") == FALSE) +		{ +			// convert meters to feet +			new_size = new_size / ONE_FOOT; +		} + +		std::string avatar_height_str = llformat("%.2f", new_size); +		mHeigthValue.setArg("[HEIGHT]", avatar_height_str); +		updateAvatarHeightLabel();  	}  	if (LLWearableType::WT_ALPHA == type) @@ -1381,4 +1438,21 @@ void LLPanelEditWearable::initPreviousAlphaTextureEntry(LLVOAvatarDefines::EText  	}  } +// handle secondlife:///app/metricsystem +class LLMetricSystemHandler : public LLCommandHandler +{ +public: +	LLMetricSystemHandler() : LLCommandHandler("metricsystem", UNTRUSTED_THROTTLE) { } + +	bool handle(const LLSD& params, const LLSD& query_map, LLMediaCtrl* web) +	{ +		// change height units TRUE for meters and FALSE for feet +		BOOL new_value = (gSavedSettings.getBOOL("HeightUnits") == FALSE) ? TRUE : FALSE; +		gSavedSettings.setBOOL("HeightUnits", new_value); +		return true; +	} +}; + +LLMetricSystemHandler gMetricSystemHandler; +  // EOF diff --git a/indra/newview/llpaneleditwearable.h b/indra/newview/llpaneleditwearable.h index 54f729fa7a..c63671fcc9 100644 --- a/indra/newview/llpaneleditwearable.h +++ b/indra/newview/llpaneleditwearable.h @@ -104,6 +104,15 @@ private:  	void initPreviousAlphaTextures();  	void initPreviousAlphaTextureEntry(LLVOAvatarDefines::ETextureIndex te); +	// callback for HeightUnits parameter. +	bool changeHeightUnits(const LLSD& new_value); + +	// updates current metric and replacemet metric label text +	void updateMetricLayout(BOOL new_value); + +	// updates avatar height label +	void updateAvatarHeightLabel(); +  	// the pointer to the wearable we're editing. NULL means we're not editing a wearable.  	LLWearable *mWearablePtr;  	LLViewerInventoryItem* mWearableItem; @@ -117,6 +126,18 @@ private:  	LLTextBox *mTxtAvatarHeight; +	// localized and parametrized strings that used to build avatar_height_label +	std::string mMeters; +	std::string mFeet; +	std::string mHeigth; +	LLUIString  mHeigthValue; +	LLUIString  mReplacementMetricUrl; + +	// color for mHeigth string +	LLUIColor mAvatarHeigthLabelColor; +	// color for mHeigthValue string +	LLUIColor mAvatarHeigthValueLabelColor; +  	// This text editor reference will change each time we edit a new wearable -   	// it will be grabbed from the currently visible panel  	LLTextEditor *mTextEditor; diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp index 7fb46fc84f..ce1131f45c 100644 --- a/indra/newview/llpanellandmarks.cpp +++ b/indra/newview/llpanellandmarks.cpp @@ -334,7 +334,7 @@ void LLLandmarksPanel::updateVerbs()  	bool landmark_selected = isLandmarkSelected();  	mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));  	mShowProfile->setEnabled(landmark_selected && isActionEnabled("more_info")); -	mShowOnMapBtn->setEnabled(true); +	mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));  	// TODO: mantipov: Uncomment when mShareBtn is supported  	// Share button should be enabled when neither a folder nor a landmark is selected diff --git a/indra/newview/llpaneloutfitedit.cpp b/indra/newview/llpaneloutfitedit.cpp index e07d5c064b..3d0684afca 100644 --- a/indra/newview/llpaneloutfitedit.cpp +++ b/indra/newview/llpaneloutfitedit.cpp @@ -189,7 +189,8 @@ LLPanelOutfitEdit::LLPanelOutfitEdit()  	mInitialized(false),  	mAddWearablesPanel(NULL),  	mWearableListMaskCollector(NULL), -	mWearableListTypeCollector(NULL) +	mWearableListTypeCollector(NULL), +	mFilterComboBox(NULL)  {  	mSavedFolderState = new LLSaveFolderState();  	mSavedFolderState->setApply(FALSE); @@ -235,12 +236,13 @@ BOOL LLPanelOutfitEdit::postBuild()  	mListViewBtn = getChild<LLButton>("list_view_btn");  	childSetCommitCallback("filter_button", boost::bind(&LLPanelOutfitEdit::showWearablesFilter, this), NULL); -	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredFolderWearablesPanel, this), NULL); -	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showFilteredWearablesPanel, this), NULL); +	childSetCommitCallback("folder_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesFolderView, this), NULL); +	childSetCommitCallback("list_view_btn", boost::bind(&LLPanelOutfitEdit::showWearablesListView, this), NULL);  	childSetCommitCallback("wearables_gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL); +	childSetCommitCallback("gear_menu_btn", boost::bind(&LLPanelOutfitEdit::onGearButtonClick, this, _1), NULL);  	mCOFWearables = getChild<LLCOFWearables>("cof_wearables_list"); -	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onOutfitItemSelectionChange, this)); +	mCOFWearables->setCommitCallback(boost::bind(&LLPanelOutfitEdit::filterWearablesBySelectedItem, this));  	mCOFWearables->getCOFCallbacks().mAddWearable = boost::bind(&LLPanelOutfitEdit::onAddWearableClicked, this);  	mCOFWearables->getCOFCallbacks().mEditWearable = boost::bind(&LLPanelOutfitEdit::onEditWearableClicked, this); @@ -258,19 +260,20 @@ BOOL LLPanelOutfitEdit::postBuild()  	mCOFDragAndDropObserver = new LLCOFDragAndDropObserver(mInventoryItemsPanel->getModel()); -	LLComboBox* type_filter = getChild<LLComboBox>("filter_wearables_combobox"); -	type_filter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); -	type_filter->removeall(); +	mFilterComboBox = getChild<LLComboBox>("filter_wearables_combobox"); +	mFilterComboBox->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onTypeFilterChanged, this, _1)); +	mFilterComboBox->removeall();  	for (U32 i = 0; i < mLookItemTypes.size(); ++i)  	{ -		type_filter->add(mLookItemTypes[i].displayName); +		mFilterComboBox->add(mLookItemTypes[i].displayName);  	} -	type_filter->setCurrentByIndex(LIT_ALL); +	mFilterComboBox->setCurrentByIndex(LIT_ALL);  	mSearchFilter = getChild<LLFilterEditor>("look_item_filter");  	mSearchFilter->setCommitCallback(boost::bind(&LLPanelOutfitEdit::onSearchEdit, this, _2)); -	childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::toggleAddWearablesPanel, this)); +	childSetAction("show_add_wearables_btn", boost::bind(&LLPanelOutfitEdit::onAddMoreButtonClicked, this)); +  	childSetAction("add_to_outfit_btn", boost::bind(&LLPanelOutfitEdit::onAddToOutfitClicked, this));  	mEditWearableBtn = getChild<LLButton>("edit_wearable_btn"); @@ -353,7 +356,7 @@ void LLPanelOutfitEdit::showWearablesFilter()  	}  } -void LLPanelOutfitEdit::showFilteredWearablesPanel() +void LLPanelOutfitEdit::showWearablesListView()  {  	if(switchPanels(mInventoryItemsPanel, mWearableItemsPanel))  	{ @@ -364,7 +367,7 @@ void LLPanelOutfitEdit::showFilteredWearablesPanel()  	mListViewBtn->setToggleState(TRUE);  } -void LLPanelOutfitEdit::showFilteredFolderWearablesPanel() +void LLPanelOutfitEdit::showWearablesFolderView()  {  	if(switchPanels(mWearableItemsPanel, mInventoryItemsPanel))  	{ @@ -377,17 +380,12 @@ void LLPanelOutfitEdit::showFilteredFolderWearablesPanel()  void LLPanelOutfitEdit::onTypeFilterChanged(LLUICtrl* ctrl)  { -	LLComboBox* type_filter = dynamic_cast<LLComboBox*>(ctrl); -	llassert(type_filter); -	if (type_filter) -	{ -		U32 curr_filter_type = type_filter->getCurrentIndex(); -		mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); +	U32 curr_filter_type = mFilterComboBox->getCurrentIndex(); +	mInventoryItemsPanel->setFilterTypes(mLookItemTypes[curr_filter_type].inventoryMask); + +	mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask); +	mWearableListManager->setFilterCollector(mWearableListMaskCollector); -		mWearableListMaskCollector->setFilterMask(mLookItemTypes[curr_filter_type].inventoryMask); -		mWearableListManager->setFilterCollector(mWearableListMaskCollector); -	} -	  	mSavedFolderState->setApply(TRUE);  	mInventoryItemsPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState); @@ -471,7 +469,7 @@ void LLPanelOutfitEdit::onAddWearableClicked(void)  	if(item)  	{ -		showFilteredWearableItemsList(item->getWearableType()); +		showFilteredWearablesListView(item->getWearableType());  	}  } @@ -481,7 +479,7 @@ void LLPanelOutfitEdit::onReplaceBodyPartMenuItemClicked(LLUUID selected_item_id  	if (item && item->getType() == LLAssetType::AT_BODYPART)  	{ -		showFilteredWearableItemsList(item->getWearableType()); +		showFilteredWearablesListView(item->getWearableType());  	}  } @@ -538,24 +536,81 @@ void LLPanelOutfitEdit::onInventorySelectionChange(const std::deque<LLFolderView  	current_item->addChild(mAddToLookBtn); */  } -void LLPanelOutfitEdit::onOutfitItemSelectionChange(void) -{	 -	LLUUID item_id = mCOFWearables->getSelectedUUID(); -	//*TODO show Edit Wearable Button +void LLPanelOutfitEdit::applyFilter(e_look_item_type type) +{ +	mFilterComboBox->setCurrentByIndex(type); +	mFilterComboBox->onCommit(); +} + +void LLPanelOutfitEdit::filterWearablesBySelectedItem(void) +{ +	if (!mAddWearablesPanel->getVisible()) return; +	 +	uuid_vec_t ids; +	mCOFWearables->getSelectedUUIDs(ids); -	LLViewerInventoryItem* item_to_remove = gInventory.getItem(item_id); -	if (!item_to_remove) return; +	bool nothing_selected = ids.empty(); +	bool one_selected = ids.size() == 1; +	bool more_than_one_selected = ids.size() > 1; +	bool is_dummy_item = (ids.size() && dynamic_cast<LLPanelDummyClothingListItem*>(mCOFWearables->getSelectedItem())); -	switch (item_to_remove->getType()) +	//resetting selection if no item is selected or than one item is selected +	if (nothing_selected || more_than_one_selected)  	{ -	case LLAssetType::AT_CLOTHING: -	case LLAssetType::AT_OBJECT: -	default: -		break; +		if (nothing_selected) +		{ +			showWearablesFolderView(); +		} + +		if (more_than_one_selected) +		{ +			showWearablesListView(); +		} +		 +		applyFilter(LIT_ALL); +		return;  	} + + +	//filter wearables by a type represented by a dummy item +	if (one_selected && is_dummy_item) +	{ +		onAddWearableClicked(); +		return; +	} + +	LLViewerInventoryItem* item = gInventory.getItem(ids[0]); +	if (!item && ids[0].notNull()) +	{ +		//Inventory misses an item with non-zero id +		showWearablesListView(); +		applyFilter(LIT_ALL); +		return; +	} + +	if (one_selected && !is_dummy_item) +	{ +		if (item->isWearableType()) +		{ +			//single clothing or bodypart item is selected +			showFilteredWearablesListView(item->getWearableType()); +			mFilterComboBox->setLabel(getString("Filter.Custom")); +			return; +		} +		else +		{ +			//attachment is selected +			showWearablesListView(); +			applyFilter(LIT_ATTACHMENT); +			return; +		} +	} +  } + +  void LLPanelOutfitEdit::update()  {  	mCOFWearables->refresh(); @@ -676,12 +731,21 @@ void LLPanelOutfitEdit::onGearButtonClick(LLUICtrl* clicked_button)  	LLMenuGL::showPopup(clicked_button, mGearMenu, 0, menu_y);  } -void LLPanelOutfitEdit::showFilteredWearableItemsList(LLWearableType::EType type) +void LLPanelOutfitEdit::onAddMoreButtonClicked() +{ +	toggleAddWearablesPanel(); +	filterWearablesBySelectedItem(); +} + +void LLPanelOutfitEdit::showFilteredWearablesListView(LLWearableType::EType type)  { +	mFilterComboBox->setLabel(getString("Filter.Custom"));  	mWearableListTypeCollector->setType(type);  	mWearableListManager->setFilterCollector(mWearableListTypeCollector);  	showAddWearablesPanel(true); -	showFilteredWearablesPanel(); +	showWearablesListView();  } + +  // EOF diff --git a/indra/newview/llpaneloutfitedit.h b/indra/newview/llpaneloutfitedit.h index 24ecf75c18..d19ede04f1 100644 --- a/indra/newview/llpaneloutfitedit.h +++ b/indra/newview/llpaneloutfitedit.h @@ -47,6 +47,7 @@  class LLButton;  class LLCOFWearables; +class LLComboBox;  class LLTextBox;  class LLInventoryCategory;  class LLOutfitObserver; @@ -94,15 +95,27 @@ public:  	void toggleAddWearablesPanel();  	void showAddWearablesPanel(bool show__add_wearables); + +	//following methods operate with "add wearables" panel  	void showWearablesFilter(); -	void showFilteredWearablesPanel(); -	void showFilteredFolderWearablesPanel(); +	void showWearablesListView(); +	void showWearablesFolderView();  	void onTypeFilterChanged(LLUICtrl* ctrl);  	void onSearchEdit(const std::string& string);  	void onInventorySelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);  	void onAddToOutfitClicked(void); -	void onOutfitItemSelectionChange(void); + +	void applyFilter(e_look_item_type type); + +	/** +	 * Filter items in views of Add Wearables Panel and show appropriate view depending on currently selected COF item(s) +	 * No COF items selected - shows the folder view, reset filter +	 * 1 COF item selected - shows the list view and filters wearables there by a wearable type of the selected item +	 * More than 1 COF item selected - shows the list view and filters it by a type of the selected item (attachment or clothing) +	 */ +	void filterWearablesBySelectedItem(void); +  	void onRemoveFromOutfitClicked(void);  	void onEditWearableClicked(void);  	void onAddWearableClicked(void); @@ -132,7 +145,8 @@ public:  private:  	void onGearButtonClick(LLUICtrl* clicked_button); -	void showFilteredWearableItemsList(LLWearableType::EType type); +	void onAddMoreButtonClicked(); +	void showFilteredWearablesListView(LLWearableType::EType type);  	LLTextBox*			mCurrentOutfitName; @@ -145,6 +159,7 @@ private:  	LLButton*			mFolderViewBtn;  	LLButton*			mListViewBtn;  	LLPanel*			mAddWearablesPanel; +	LLComboBox*			mFilterComboBox;  	LLFindNonLinksByMask*  mWearableListMaskCollector;  	LLFindWearablesOfType* mWearableListTypeCollector; @@ -162,6 +177,8 @@ private:  	bool				mInitialized;  	std::auto_ptr<LLSaveOutfitComboBtn> mSaveComboBtn; + +  };  #endif // LL_LLPANELOUTFITEDIT_H diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp index e8b6c6bfe5..494cba8c6f 100644 --- a/indra/newview/llpanelteleporthistory.cpp +++ b/indra/newview/llpanelteleporthistory.cpp @@ -564,6 +564,7 @@ void LLTeleportHistoryPanel::updateVerbs()  	{  		mTeleportBtn->setEnabled(false);  		mShowProfile->setEnabled(false); +		mShowOnMapBtn->setEnabled(false);  		return;  	} @@ -571,7 +572,7 @@ void LLTeleportHistoryPanel::updateVerbs()  	mTeleportBtn->setEnabled(NULL != itemp);  	mShowProfile->setEnabled(NULL != itemp); -	mShowOnMapBtn->setEnabled(true); +	mShowOnMapBtn->setEnabled(NULL != itemp);  }  void LLTeleportHistoryPanel::getNextTab(const LLDate& item_date, S32& tab_idx, LLDate& tab_date) diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp index 6c6eda2e68..db1f4dc4cb 100644 --- a/indra/newview/lltoastalertpanel.cpp +++ b/indra/newview/lltoastalertpanel.cpp @@ -172,6 +172,7 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  	params.tab_stop(false);  	params.wrap(true);  	params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP); +	params.allow_scroll(true);  	LLTextBox * msg_box = LLUICtrlFactory::create<LLTextBox> (params);  	// Compute max allowable height for the dialog text, so we can allocate @@ -180,9 +181,16 @@ LLToastAlertPanel::LLToastAlertPanel( LLNotificationPtr notification, bool modal  			gFloaterView->getRect().getHeight()  			- LINE_HEIGHT			// title bar  			- 3*VPAD - BTN_HEIGHT; +	// reshape to calculate real text width and height  	msg_box->reshape( MAX_ALLOWED_MSG_WIDTH, max_allowed_msg_height );  	msg_box->setValue(msg); -	msg_box->reshapeToFitText(); + +	S32 pixel_width = msg_box->getTextPixelWidth(); +	S32 pixel_height = msg_box->getTextPixelHeight(); + +	// We should use some space to prevent set textbox's scroller visible when it is unnecessary. +	msg_box->reshape( llmin(MAX_ALLOWED_MSG_WIDTH,pixel_width + 2 * msg_box->getHPad() + HPAD), +		llmin(max_allowed_msg_height,pixel_height + 2 * msg_box->getVPad())  ) ;  	const LLRect& text_rect = msg_box->getRect();  	S32 dialog_width = llmax( btn_total_width, text_rect.getWidth() ) + 2 * HPAD; diff --git a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml index b5eda8e999..c4e31ed180 100644 --- a/indra/newview/skins/default/xui/en/menu_outfit_gear.xml +++ b/indra/newview/skins/default/xui/en/menu_outfit_gear.xml @@ -170,7 +170,7 @@      <menu_item_separator />      <menu_item_call -     label="Rename" +     label="Rename Outfit"       layout="topleft"       name="rename">          <on_click diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml index 439f67e7b1..76a41a3b13 100644 --- a/indra/newview/skins/default/xui/en/notifications.xml +++ b/indra/newview/skins/default/xui/en/notifications.xml @@ -6207,7 +6207,7 @@ The button will be shown when there is enough space for it.     icon="notifytip.tga"     name="ShareNotification"     type="notifytip"> -Drag items from inventory onto a person in the resident picker +Select residents to share with.    </notification>    <notification     icon="notifytip.tga" diff --git a/indra/newview/skins/default/xui/en/panel_edit_shape.xml b/indra/newview/skins/default/xui/en/panel_edit_shape.xml index cf15fb0455..d295f5fe4a 100644 --- a/indra/newview/skins/default/xui/en/panel_edit_shape.xml +++ b/indra/newview/skins/default/xui/en/panel_edit_shape.xml @@ -8,19 +8,22 @@  	 name="edit_shape_panel"  	 top_pad="10"  	 width="333" > -	 <text -		 follows="top|left|right" -		 font="SansSerifSmallBold" -		 halign="right" -		 height="12" -		 layout="topleft" -		 left="0" -		 name="avatar_height" -		 text_color="EmphasisColor" -		 top="0" -		 width="310"> -		 [HEIGHT] Meters tall -	 </text> +     <string name="meters">Meters</string> +     <string name="feet">Feet</string> +     <string name="height">Height:</string> +     <string name="heigth_label_color" translate="false">White_50</string> +     <string name="heigth_value_label_color" translate="false">White</string> +     <text +         follows="top|left|right" +         font="SansSerifSmallBold" +         halign="right" +         height="12" +         layout="topleft" +         left="0" +         name="avatar_height" +         top="0" +         width="310"> +     </text>       <panel           border="false"           bg_alpha_color="DkGray2" diff --git a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml index c9802a269c..741f60669a 100644 --- a/indra/newview/skins/default/xui/en/panel_outfit_edit.xml +++ b/indra/newview/skins/default/xui/en/panel_outfit_edit.xml @@ -51,6 +51,7 @@      <string name="Filter.All" value="All"/>      <string name="Filter.Clothes/Body" value="Clothes/Body"/>      <string name="Filter.Objects" value="Objects"/> +    <string name="Filter.Custom" value="Custom filter"/>      <button diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml index 0d14a6b3c8..361af0e8fb 100644 --- a/indra/newview/skins/default/xui/en/strings.xml +++ b/indra/newview/skins/default/xui/en/strings.xml @@ -3181,7 +3181,7 @@ Abuse Report</string>    <!-- language specific white-space characters, delimiters, spacers, item separation symbols -->    <string name="sentences_separator" value=" "></string> -  <string name="words_separator">, </string> +  <string name="words_separator" value=", "/>    <string name="server_is_down">  	Despite our best efforts, something unexpected has gone wrong. | 
