diff options
Diffstat (limited to 'indra/llcommon')
43 files changed, 1896 insertions, 2705 deletions
diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index 9ead183a9e..2a036df06e 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -9,6 +9,7 @@ include(Linking)  include(Boost)  include(Pth)  include(LLSharedLibs) +include(GoogleBreakpad)  include(GooglePerfTools)  include(Copy3rdPartyLibs) @@ -35,6 +36,7 @@ set(llcommon_SOURCE_FILES      llbase32.cpp      llbase64.cpp      llcommon.cpp +    llcommonutils.cpp      llcoros.cpp      llcrc.cpp      llcriticaldamp.cpp @@ -50,6 +52,7 @@ set(llcommon_SOURCE_FILES      lleventdispatcher.cpp      lleventfilter.cpp      llevents.cpp +    lleventtimer.cpp      llfasttimer_class.cpp      llfile.cpp      llfindlocale.cpp @@ -123,6 +126,7 @@ set(llcommon_HEADER_FILES      llchat.h      llclickaction.h      llcommon.h +    llcommonutils.h      llcoros.h      llcrc.h      llcriticaldamp.h @@ -164,7 +168,6 @@ set(llcommon_HEADER_FILES      llhttpstatuscodes.h      llindexedqueue.h      llinstancetracker.h -    llinstancetracker.h      llkeythrottle.h      lllazy.h      lllistenerwrapper.h @@ -230,7 +233,6 @@ set(llcommon_HEADER_FILES      metaclasst.h      metaproperty.h      metapropertyt.h -    processor.h      reflective.h      reflectivet.h      roles_constants.h @@ -257,6 +259,7 @@ endif(LLCOMMON_LINK_SHARED)  target_link_libraries(      llcommon +    ${BREAKPAD_EXCEPTION_HANDLER_LIBRARIES}      ${APRUTIL_LIBRARIES}      ${APR_LIBRARIES}      ${EXPAT_LIBRARIES} @@ -288,6 +291,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/llapp.cpp b/indra/llcommon/llapp.cpp index 968b92d1e7..0447ca93f5 100644 --- a/indra/llcommon/llapp.cpp +++ b/indra/llcommon/llapp.cpp @@ -30,6 +30,14 @@   * $/LicenseInfo$   */ +#include <cstdlib> + +#ifdef LL_DARWIN +#include <sys/types.h> +#include <unistd.h> +#include <sys/sysctl.h> +#endif +  #include "linden_common.h"  #include "llapp.h" @@ -41,7 +49,10 @@  #include "lllivefile.h"  #include "llmemory.h"  #include "llstl.h" // for DeletePointer() -#include "lltimer.h" +#include "llstring.h" +#include "lleventtimer.h" + +#include "google_breakpad/exception_handler.h"  //  // Signal handling @@ -51,11 +62,22 @@  #if LL_WINDOWS  LONG WINAPI default_windows_exception_handler(struct _EXCEPTION_POINTERS *exception_infop);  BOOL ConsoleCtrlHandler(DWORD fdwCtrlType); +bool windows_post_minidump_callback(const wchar_t* dump_path, +									const wchar_t* minidump_id, +									void* context, +									EXCEPTION_POINTERS* exinfo, +									MDRawAssertionInfo* assertion, +									bool succeeded);  #else  # include <signal.h>  # include <unistd.h> // for fork()  void setup_signals();  void default_unix_signal_handler(int signum, siginfo_t *info, void *); + +// Called by breakpad exception handler after the minidump has been generated. +bool unix_post_minidump_callback(const char *dump_dir, +					  const char *minidump_id, +					  void *context, bool succeeded);  # if LL_DARWIN  /* OSX doesn't support SIGRT* */  S32 LL_SMACKDOWN_SIGNAL = SIGUSR1; @@ -81,7 +103,6 @@ BOOL LLApp::sLogInSignal = FALSE;  // static  LLApp::EAppStatus LLApp::sStatus = LLApp::APP_STATUS_STOPPED; // Keeps track of application status  LLAppErrorHandler LLApp::sErrorHandler = NULL; -LLAppErrorHandler LLApp::sSyncErrorHandler = NULL;  BOOL LLApp::sErrorThreadRunning = FALSE;  #if !LL_WINDOWS  LLApp::child_map LLApp::sChildMap; @@ -123,7 +144,12 @@ void LLApp::commonCtor()  	// Set the application to this instance.  	sApplication = this; - +	 +	mExceptionHandler = 0; +	 +	// initialize the buffer to write the minidump filename to +	// (this is used to avoid allocating memory in the crash handler) +	memset(minidump_path, 0, MAX_MINDUMP_PATH_LENGTH);  }  LLApp::LLApp(LLErrorThread *error_thread) : @@ -152,6 +178,8 @@ LLApp::~LLApp()  		delete mThreadErrorp;  		mThreadErrorp = NULL;  	} +	 +	if(mExceptionHandler != 0) delete mExceptionHandler;  	LLCommon::cleanupClass();  } @@ -262,19 +290,18 @@ void LLApp::setupErrorHandling()  	// occasionally checks to see if the app is in an error state, and sees if it needs to be run.  #if LL_WINDOWS -	// Windows doesn't have the same signal handling mechanisms as UNIX, thus APR doesn't provide -	// a signal handling thread implementation. -	// What we do is install an unhandled exception handler, which will try to do the right thing -	// in the case of an error (generate a minidump) - -	// Disable this until the viewer gets ported so server crashes can be JIT debugged. -	//LPTOP_LEVEL_EXCEPTION_FILTER prev_filter; -	//prev_filter = SetUnhandledExceptionFilter(default_windows_exception_handler); -  	// This sets a callback to handle w32 signals to the console window.  	// The viewer shouldn't be affected, sicne its a windowed app.  	SetConsoleCtrlHandler( (PHANDLER_ROUTINE) ConsoleCtrlHandler, TRUE); +	// Install the Google Breakpad crash handler for Windows +	if(mExceptionHandler == 0) +	{ +		llwarns << "adding breakpad exception handler" << llendl; +		mExceptionHandler = new google_breakpad::ExceptionHandler( +			L"C:\\Temp\\", 0, windows_post_minidump_callback, 0, google_breakpad::ExceptionHandler::HANDLER_ALL); +	} +  #else  	//  	// Start up signal handling. @@ -282,9 +309,49 @@ void LLApp::setupErrorHandling()  	// There are two different classes of signals.  Synchronous signals are delivered to a specific  	// thread, asynchronous signals can be delivered to any thread (in theory)  	// -  	setup_signals(); - +	 +	// Add google breakpad exception handler configured for Darwin/Linux. +	bool installHandler = true; +#ifdef LL_DARWIN +	// For the special case of Darwin, we do not want to install the handler if +	// the process is being debugged as the app will exit with value ABRT (6) if +	// we do.  Unfortunately, the code below which performs that test relies on +	// the structure kinfo_proc which has been tagged by apple as an unstable +	// API.  We disable this test for shipping versions to avoid conflicts with +	// future releases of Darwin.  This test is really only needed for developers +	// starting the app from a debugger anyway. +	#ifndef LL_RELEASE_FOR_DOWNLOAD +    int mib[4]; +	mib[0] = CTL_KERN; +	mib[1] = KERN_PROC; +	mib[2] = KERN_PROC_PID; +	mib[3] = getpid(); +	 +	struct kinfo_proc info; +	memset(&info, 0, sizeof(info)); +	 +	size_t size = sizeof(info); +	int result = sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0); +	if((result == 0) || (errno == ENOMEM)) +	{ +		// P_TRACED flag is set, so this process is being debugged; do not install +		// the handler +		if(info.kp_proc.p_flag & P_TRACED) installHandler = false; +	} +	else +	{ +		// Failed to discover if the process is being debugged; default to +		// installing the handler. +		installHandler = true; +	} +	#endif +#endif +	if(installHandler && (mExceptionHandler == 0)) +	{ +		std::string dumpPath = "/tmp/"; +		mExceptionHandler = new google_breakpad::ExceptionHandler(dumpPath, 0, &unix_post_minidump_callback, 0, true); +	}  #endif  	startErrorThread(); @@ -310,21 +377,6 @@ void LLApp::setErrorHandler(LLAppErrorHandler handler)  	LLApp::sErrorHandler = handler;  } - -void LLApp::setSyncErrorHandler(LLAppErrorHandler handler) -{ -	LLApp::sSyncErrorHandler = handler; -} - -// static -void LLApp::runSyncErrorHandler() -{ -	if (LLApp::sSyncErrorHandler) -	{ -		LLApp::sSyncErrorHandler(); -	} -} -  // static  void LLApp::runErrorHandler()  { @@ -337,7 +389,6 @@ void LLApp::runErrorHandler()  	LLApp::setStopped();  } -  // static  void LLApp::setStatus(EAppStatus status)  { @@ -348,15 +399,27 @@ void LLApp::setStatus(EAppStatus status)  // static  void LLApp::setError()  { -	if (!isError()) -	{ -		// perform any needed synchronous error-handling -		runSyncErrorHandler(); -		// set app status to ERROR so that the LLErrorThread notices -		setStatus(APP_STATUS_ERROR); -	} +	// set app status to ERROR so that the LLErrorThread notices +	setStatus(APP_STATUS_ERROR);  } +void LLApp::setMiniDumpDir(const std::string &path) +{ +	if(mExceptionHandler == 0) return; +#ifdef LL_WINDOWS +	wchar_t buffer[MAX_MINDUMP_PATH_LENGTH]; +	mbstowcs(buffer, path.c_str(), MAX_MINDUMP_PATH_LENGTH); +	mExceptionHandler->set_dump_path(std::wstring(buffer)); +#else +	mExceptionHandler->set_dump_path(path); +#endif +} + +void LLApp::writeMiniDump() +{ +	if(mExceptionHandler == 0) return; +	mExceptionHandler->WriteMinidump(); +}  // static  void LLApp::setQuitting() @@ -587,6 +650,7 @@ void setup_signals()  	// Asynchronous signals that result in core  	sigaction(SIGQUIT, &act, NULL); +	  }  void clear_signals() @@ -765,4 +829,97 @@ void default_unix_signal_handler(int signum, siginfo_t *info, void *)  	}  } +bool unix_post_minidump_callback(const char *dump_dir, +					  const char *minidump_id, +					  void *context, bool succeeded) +{ +	// Copy minidump file path into fixed buffer in the app instance to avoid +	// heap allocations in a crash handler. +	 +	// path format: <dump_dir>/<minidump_id>.dmp +	int dirPathLength = strlen(dump_dir); +	int idLength = strlen(minidump_id); +	 +	// The path must not be truncated. +	llassert((dirPathLength + idLength + 5) <= LLApp::MAX_MINDUMP_PATH_LENGTH); +	 +	char * path = LLApp::instance()->getMiniDumpFilename(); +	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; +	strncpy(path, dump_dir, remaining); +	remaining -= dirPathLength; +	path += dirPathLength; +	if (remaining > 0 && dirPathLength > 0 && path[-1] != '/') +	{ +		*path++ = '/'; +		--remaining; +	} +	if (remaining > 0) +	{ +		strncpy(path, minidump_id, remaining); +		remaining -= idLength; +		path += idLength; +		strncpy(path, ".dmp", remaining); +	} +	 +	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; +	LLApp::runErrorHandler(); +	return true; +}  #endif // !WINDOWS + +#ifdef LL_WINDOWS +bool windows_post_minidump_callback(const wchar_t* dump_path, +									const wchar_t* minidump_id, +									void* context, +									EXCEPTION_POINTERS* exinfo, +									MDRawAssertionInfo* assertion, +									bool succeeded) +{ +	char * path = LLApp::instance()->getMiniDumpFilename(); +	S32 remaining = LLApp::MAX_MINDUMP_PATH_LENGTH; +	size_t bytesUsed; + +	bytesUsed = wcstombs(path, dump_path, static_cast<size_t>(remaining)); +	remaining -= bytesUsed; +	path += bytesUsed; +	if(remaining > 0 && bytesUsed > 0 && path[-1] != '\\') +	{ +		*path++ = '\\'; +		--remaining; +	} +	if(remaining > 0) +	{ +		bytesUsed = wcstombs(path, minidump_id, static_cast<size_t>(remaining)); +		remaining -= bytesUsed; +		path += bytesUsed; +	} +	if(remaining > 0) +	{ +		strncpy(path, ".dmp", remaining); +	} + +	llinfos << "generated minidump: " << LLApp::instance()->getMiniDumpFilename() << llendl; +    // *NOTE:Mani - this code is stolen from LLApp, where its never actually used. +	//OSMessageBox("Attach Debugger Now", "Error", OSMB_OK); +    // *TODO: Translate the signals/exceptions into cross-platform stuff +	// Windows implementation +	llinfos << "Entering Windows Exception Handler..." << llendl; + +	if (LLApp::isError()) +	{ +		llwarns << "Got another fatal signal while in the error handler, die now!" << llendl; +	} + +	// Flag status to error, so thread_error starts its work +	LLApp::setError(); + +	// Block in the exception handler until the app has stopped +	// This is pretty sketchy, but appears to work just fine +	while (!LLApp::isStopped()) +	{ +		ms_sleep(10); +	} + +	return true; +} +#endif diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h index 27a52cdd99..fef05a7939 100644 --- a/indra/llcommon/llapp.h +++ b/indra/llcommon/llapp.h @@ -66,6 +66,10 @@ public:  };  #endif +namespace google_breakpad { +	class ExceptionHandler; // See exception_handler.h +} +  class LL_COMMON_API LLApp : public LLOptionInterface  {  	friend class LLErrorThread; @@ -227,15 +231,27 @@ public:  	void setupErrorHandling();  	void setErrorHandler(LLAppErrorHandler handler); -	void setSyncErrorHandler(LLAppErrorHandler handler); +	static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred.  	//@} +	 +	// the maximum length of the minidump filename returned by getMiniDumpFilename() +	static const U32 MAX_MINDUMP_PATH_LENGTH = 256; + +	// change the directory where Breakpad minidump files are written to +	void setMiniDumpDir(const std::string &path); + +	// Return the Google Breakpad minidump filename after a crash. +	char *getMiniDumpFilename() { return minidump_path; } + +	// Write out a Google Breakpad minidump file. +	void writeMiniDump();  #if !LL_WINDOWS  	//  	// Child process handling (Unix only for now)  	//  	// Set a callback to be run on exit of a child process -	// WARNING!  This callback is run from the signal handler due to the extreme crappiness of +	// WARNING!  This callback is run from the signal handler due to  	// Linux threading requiring waitpid() to be called from the thread that spawned the process.  	// At some point I will make this more behaved, but I'm not going to fix this right now - djs  	void setChildCallback(pid_t pid, LLAppChildCallback callback); @@ -286,15 +302,14 @@ protected:  private:  	void startErrorThread(); -	static void runErrorHandler(); // run shortly after we detect an error, ran in the relatively robust context of the LLErrorThread - preferred. -	static void runSyncErrorHandler(); // run IMMEDIATELY when we get an error, ran in the context of the faulting thread. +	// Contains the filename of the minidump file after a crash. +	char minidump_path[MAX_MINDUMP_PATH_LENGTH];  	// *NOTE: On Windows, we need a routine to reset the structured  	// exception handler when some evil driver has taken it over for  	// their own purposes  	typedef int(*signal_handler_func)(int signum);  	static LLAppErrorHandler sErrorHandler; -	static LLAppErrorHandler sSyncErrorHandler;  	// Default application threads  	LLErrorThread* mThreadErrorp;		// Waits for app to go to status ERROR, then runs the error callback @@ -315,6 +330,8 @@ private:  private:  	// the static application instance if it was created.  	static LLApp* sApplication; +	 +	google_breakpad::ExceptionHandler * mExceptionHandler;  #if !LL_WINDOWS diff --git a/indra/llcommon/llapr.cpp b/indra/llcommon/llapr.cpp index ed70b1d9f2..7330b00bcf 100644 --- a/indra/llcommon/llapr.cpp +++ b/indra/llcommon/llapr.cpp @@ -543,14 +543,13 @@ S32 LLAPRFile::readEx(const std::string& filename, void *buf, S32 offset, S32 nb  		return 0;  	} -	S32 off; -	if (offset < 0) -		off = LLAPRFile::seek(file_handle, APR_END, 0); -	else -		off = LLAPRFile::seek(file_handle, APR_SET, offset); +	llassert(offset >= 0); + +	if (offset > 0) +		offset = LLAPRFile::seek(file_handle, APR_SET, offset);  	apr_size_t bytes_read; -	if (off < 0) +	if (offset < 0)  	{  		bytes_read = 0;  	} diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h index b05a222b33..08cf11e593 100644 --- a/indra/llcommon/llapr.h +++ b/indra/llcommon/llapr.h @@ -182,7 +182,7 @@ typedef LLAtomic32<U32> LLAtomicU32;  typedef LLAtomic32<S32> LLAtomicS32;  // File IO convenience functions. -// Returns NULL if the file fails to openm sets *sizep to file size of not NULL +// Returns NULL if the file fails to open, sets *sizep to file size if not NULL  // abbreviated flags  #define LL_APR_R (APR_READ) // "r"  #define LL_APR_W (APR_CREATE|APR_TRUNCATE|APR_WRITE) // "w" @@ -200,7 +200,7 @@ typedef LLAtomic32<S32> LLAtomicS32;  //      especially do not put some time-costly operations between open() and close().  //      otherwise it might lock the APRFilePool.  //there are two different apr_pools the APRFile can use: -//      1, a temperary pool passed to an APRFile function, which is used within this function and only once. +//      1, a temporary pool passed to an APRFile function, which is used within this function and only once.  //      2, a global pool.  // @@ -255,12 +255,12 @@ public:  	// Returns bytes read/written, 0 if read/write fails:  	static S32 readEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	 -	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL);	 +	static S32 writeEx(const std::string& filename, void *buf, S32 offset, S32 nbytes, LLVolatileAPRPool* pool = NULL); // offset<0 means append  //*******************************************************************************************************************************  };  /** - * @brief Function which approprately logs error or remains quiet on + * @brief Function which appropriately logs error or remains quiet on   * APR_SUCCESS.   * @return Returns <code>true</code> if status is an error condition.   */ diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index 6d5b12d840..2cd29448ae 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -45,12 +45,16 @@ struct AssetEntry : public LLDictionaryEntry  	AssetEntry(const char *desc_name,  			   const char *type_name, 	// 8 character limit!  			   const char *human_name, 	// for decoding to human readable form; put any and as many printable characters you want in each one -			   bool can_link) 			// can you create a link to this type? +			   bool can_link, 			// can you create a link to this type? +			   bool can_fetch, 			// can you fetch this asset by ID? +			   bool can_know) 			// can you see this asset's ID?  		:  		LLDictionaryEntry(desc_name),  		mTypeName(type_name),  		mHumanName(human_name), -		mCanLink(can_link) +		mCanLink(can_link), +		mCanFetch(can_fetch), +		mCanKnow(can_know)  	{  		llassert(strlen(mTypeName) <= 8);  	} @@ -58,6 +62,8 @@ struct AssetEntry : public LLDictionaryEntry  	const char *mTypeName;  	const char *mHumanName;  	bool mCanLink; +	bool mCanFetch; +	bool mCanKnow;  };  class LLAssetDictionary : public LLSingleton<LLAssetDictionary>, @@ -69,32 +75,32 @@ public:  LLAssetDictionary::LLAssetDictionary()  { -	//       												   DESCRIPTION			TYPE NAME	HUMAN NAME			CAN LINK?	 -	//      												  |--------------------|-----------|-------------------|-----------| -	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			FALSE)); -	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			FALSE)); -	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		FALSE)); -	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			FALSE)); -	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	FALSE)); -	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			TRUE)); -	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			TRUE)); -	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		FALSE)); -	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			TRUE)); -	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		FALSE)); -	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		FALSE)); -	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		FALSE)); -	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		TRUE)); -	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			FALSE)); -	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		FALSE)); -	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		FALSE)); -	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		FALSE)); -	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			TRUE)); -	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			FALSE)); - -	addEntry(LLAssetType::AT_LINK, 				new AssetEntry("LINK",				"link",		"symbolic link",	FALSE)); -	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"symbolic folder link", FALSE)); - -	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		FALSE)); +	//       												   DESCRIPTION			TYPE NAME	HUMAN NAME			CAN LINK?   CAN FETCH?  CAN KNOW?	 +	//      												  |--------------------|-----------|-------------------|-----------|-----------|---------| +	addEntry(LLAssetType::AT_TEXTURE, 			new AssetEntry("TEXTURE",			"texture",	"texture",			true,		false,		true)); +	addEntry(LLAssetType::AT_SOUND, 			new AssetEntry("SOUND",				"sound",	"sound",			true,		true,		true)); +	addEntry(LLAssetType::AT_CALLINGCARD, 		new AssetEntry("CALLINGCARD",		"callcard",	"calling card",		true,		false,		false)); +	addEntry(LLAssetType::AT_LANDMARK, 			new AssetEntry("LANDMARK",			"landmark",	"landmark",			true,		true,		true)); +	addEntry(LLAssetType::AT_SCRIPT, 			new AssetEntry("SCRIPT",			"script",	"legacy script",	true,		false,		false)); +	addEntry(LLAssetType::AT_CLOTHING, 			new AssetEntry("CLOTHING",			"clothing",	"clothing",			true,		true,		true)); +	addEntry(LLAssetType::AT_OBJECT, 			new AssetEntry("OBJECT",			"object",	"object",			true,		false,		false)); +	addEntry(LLAssetType::AT_NOTECARD, 			new AssetEntry("NOTECARD",			"notecard",	"note card",		true,		false,		true)); +	addEntry(LLAssetType::AT_CATEGORY, 			new AssetEntry("CATEGORY",			"category",	"folder",			true,		false,		false)); +	addEntry(LLAssetType::AT_LSL_TEXT, 			new AssetEntry("LSL_TEXT",			"lsltext",	"lsl2 script",		true,		false,		false)); +	addEntry(LLAssetType::AT_LSL_BYTECODE, 		new AssetEntry("LSL_BYTECODE",		"lslbyte",	"lsl bytecode",		true,		false,		false)); +	addEntry(LLAssetType::AT_TEXTURE_TGA, 		new AssetEntry("TEXTURE_TGA",		"txtr_tga",	"tga texture",		true,		false,		false)); +	addEntry(LLAssetType::AT_BODYPART, 			new AssetEntry("BODYPART",			"bodypart",	"body part",		true,		true,		true)); +	addEntry(LLAssetType::AT_SOUND_WAV, 		new AssetEntry("SOUND_WAV",			"snd_wav",	"sound",			true,		false,		false)); +	addEntry(LLAssetType::AT_IMAGE_TGA, 		new AssetEntry("IMAGE_TGA",			"img_tga",	"targa image",		true,		false,		false)); +	addEntry(LLAssetType::AT_IMAGE_JPEG, 		new AssetEntry("IMAGE_JPEG",		"jpeg",		"jpeg image",		true,		false,		false)); +	addEntry(LLAssetType::AT_ANIMATION, 		new AssetEntry("ANIMATION",			"animatn",	"animation",		true,		true,		true)); +	addEntry(LLAssetType::AT_GESTURE, 			new AssetEntry("GESTURE",			"gesture",	"gesture",			true,		true,		true)); +	addEntry(LLAssetType::AT_SIMSTATE, 			new AssetEntry("SIMSTATE",			"simstate",	"simstate",			false,		false,		false)); + +	addEntry(LLAssetType::AT_LINK, 				new AssetEntry("LINK",				"link",		"sym link",			false,		false,		true)); +	addEntry(LLAssetType::AT_LINK_FOLDER, 		new AssetEntry("FOLDER_LINK",		"link_f", 	"sym folder link",	false,		false,		true)); + +	addEntry(LLAssetType::AT_NONE, 				new AssetEntry("NONE",				"-1",		NULL,		  		false,		false,		false));  };  // static @@ -225,3 +231,27 @@ const std::string &LLAssetType::badLookup()  	return sBadLookup;  } + +// static +bool LLAssetType::lookupIsAssetFetchByIDAllowed(EType asset_type) +{ +	const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); +	const AssetEntry *entry = dict->lookup(asset_type); +	if (entry) +	{ +		return entry->mCanFetch; +	} +	return false; +} + +// static +bool LLAssetType::lookupIsAssetIDKnowable(EType asset_type) +{ +	const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); +	const AssetEntry *entry = dict->lookup(asset_type); +	if (entry) +	{ +		return entry->mCanKnow; +	} +	return false; +} diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index c7bbc2e74a..2c2dc27aaa 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -146,6 +146,9 @@ public:  	static bool 				lookupCanLink(EType asset_type);  	static bool 				lookupIsLinkType(EType asset_type); +	static bool 				lookupIsAssetFetchByIDAllowed(EType asset_type); // the asset allows direct download +	static bool 				lookupIsAssetIDKnowable(EType asset_type); // asset data can be known by the viewer +	  	static const std::string&	badLookup(); // error string when a lookup fails  protected: diff --git a/indra/llcommon/llchat.h b/indra/llcommon/llchat.h index a77bd211f3..63cce24005 100644 --- a/indra/llcommon/llchat.h +++ b/indra/llcommon/llchat.h @@ -43,7 +43,8 @@ typedef enum e_chat_source_type  {  	CHAT_SOURCE_SYSTEM = 0,  	CHAT_SOURCE_AGENT = 1, -	CHAT_SOURCE_OBJECT = 2 +	CHAT_SOURCE_OBJECT = 2, +	CHAT_SOURCE_UNKNOWN = 3  } EChatSourceType;  typedef enum e_chat_type @@ -68,7 +69,8 @@ typedef enum e_chat_audible_level  typedef enum e_chat_style  {  	CHAT_STYLE_NORMAL, -	CHAT_STYLE_IRC +	CHAT_STYLE_IRC, +	CHAT_STYLE_HISTORY  }EChatStyle;  // A piece of chat @@ -80,6 +82,7 @@ public:  		mFromName(),  		mFromID(),  		mNotifId(), +		mOwnerID(),  		mSourceType(CHAT_SOURCE_AGENT),  		mChatType(CHAT_TYPE_NORMAL),  		mAudible(CHAT_AUDIBLE_FULLY), @@ -96,6 +99,7 @@ public:  	std::string		mFromName;	// agent or object name  	LLUUID			mFromID;	// agent id or object id  	LLUUID			mNotifId; +	LLUUID			mOwnerID;  	EChatSourceType	mSourceType;  	EChatType		mChatType;  	EChatAudible	mAudible; diff --git a/indra/llcommon/llcommonutils.cpp b/indra/llcommon/llcommonutils.cpp new file mode 100644 index 0000000000..0022dc6915 --- /dev/null +++ b/indra/llcommon/llcommonutils.cpp @@ -0,0 +1,61 @@ +/** + * @file llcommonutils.h + * @brief Commin utils + * + * $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 "llcommonutils.h" + +void LLCommonUtils::computeDifference( +	const uuid_vec_t& vnew, +	const uuid_vec_t& vcur, +	uuid_vec_t& vadded, +	uuid_vec_t& vremoved) +{ +	uuid_vec_t vnew_copy(vnew); +	uuid_vec_t vcur_copy(vcur); + +	std::sort(vnew_copy.begin(), vnew_copy.end()); +	std::sort(vcur_copy.begin(), vcur_copy.end()); + +	size_t maxsize = llmax(vnew_copy.size(), vcur_copy.size()); +	vadded.resize(maxsize); +	vremoved.resize(maxsize); + +	uuid_vec_t::iterator it; +	// what was removed +	it = set_difference(vcur_copy.begin(), vcur_copy.end(), vnew_copy.begin(), vnew_copy.end(), vremoved.begin()); +	vremoved.erase(it, vremoved.end()); + +	// what was added +	it = set_difference(vnew_copy.begin(), vnew_copy.end(), vcur_copy.begin(), vcur_copy.end(), vadded.begin()); +	vadded.erase(it, vadded.end()); +} + +// EOF diff --git a/indra/llcommon/llcommonutils.h b/indra/llcommon/llcommonutils.h new file mode 100644 index 0000000000..ad0d884e37 --- /dev/null +++ b/indra/llcommon/llcommonutils.h @@ -0,0 +1,56 @@ +/** + * @file llcommonutils.h + * @brief Common utils + * + * $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$ + */ + +#ifndef LL_LLCOMMONUTILS_H +#define LL_LLCOMMONUTILS_H + +namespace LLCommonUtils +{ +	/** +	 * Computes difference between 'vnew' and 'vcur' vectors. +	 * Items present in 'vnew' and missing in 'vcur' are treated as added and are copied into 'vadded' +	 * Items missing in 'vnew' and present in 'vcur' are treated as removed and are copied into 'vremoved' +	 * +	 * @param vnew[in] - incoming IDs +	 * @param vcur[in] - current IDs +	 * @param vadded[out] - difference between incoming and current IDS - added IDs +	 * @param vremoved[out] - difference between incoming and current IDS - removed IDs +	 */ +	LL_COMMON_API void computeDifference( +		const uuid_vec_t& vnew, +		const uuid_vec_t& vcur, +		uuid_vec_t& vadded, +		uuid_vec_t& vremoved); +}; + +#endif //LL_LLCOMMONUTILS_H + +// EOF diff --git a/indra/llcommon/llcursortypes.cpp b/indra/llcommon/llcursortypes.cpp index 23ede97af3..6751c235f6 100644 --- a/indra/llcommon/llcursortypes.cpp +++ b/indra/llcommon/llcursortypes.cpp @@ -72,6 +72,9 @@ ECursorType getCursorFromString(const std::string& cursor_string)  		cursor_string_table["UI_CURSOR_TOOLPAUSE"] = UI_CURSOR_TOOLPAUSE;  		cursor_string_table["UI_CURSOR_TOOLMEDIAOPEN"] = UI_CURSOR_TOOLMEDIAOPEN;  		cursor_string_table["UI_CURSOR_PIPETTE"] = UI_CURSOR_PIPETTE; +		cursor_string_table["UI_CURSOR_TOOLSIT"] = UI_CURSOR_TOOLSIT; +		cursor_string_table["UI_CURSOR_TOOLBUY"] = UI_CURSOR_TOOLBUY; +		cursor_string_table["UI_CURSOR_TOOLOPEN"] = UI_CURSOR_TOOLOPEN;  	}  	std::map<std::string,U32>::const_iterator iter = cursor_string_table.find(cursor_string); diff --git a/indra/llcommon/llcursortypes.h b/indra/llcommon/llcursortypes.h index a1b8178bfe..143c2c64cf 100644 --- a/indra/llcommon/llcursortypes.h +++ b/indra/llcommon/llcursortypes.h @@ -68,6 +68,9 @@ enum ECursorType {  	UI_CURSOR_TOOLPAUSE,  	UI_CURSOR_TOOLMEDIAOPEN,  	UI_CURSOR_PIPETTE, +	UI_CURSOR_TOOLSIT, +	UI_CURSOR_TOOLBUY, +	UI_CURSOR_TOOLOPEN,  	UI_CURSOR_COUNT			// Number of elements in this enum (NOT a cursor)  }; diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index de7f2ead74..a7ef28b431 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -248,8 +248,27 @@ bool LLDate::fromStream(std::istream& s)  		s >> fractional;  		seconds_since_epoch += fractional;  	} -	c = s.get(); // skip the Z -	if (c != 'Z') { return false; } + +	c = s.peek(); // check for offset +	if (c == '+' || c == '-') +	{ +		S32 offset_sign = (c == '+') ? 1 : -1; +		S32 offset_hours = 0; +		S32 offset_minutes = 0; +		S32 offset_in_seconds = 0; + +		s >> offset_hours; + +		c = s.get(); // skip the colon a get the minutes if there are any +		if (c == ':') +		{		 +			s >> offset_minutes; +		} +		 +		offset_in_seconds =  (offset_hours * 60 + offset_sign * offset_minutes) * 60; +		seconds_since_epoch -= offset_in_seconds; +	} +	else if (c != 'Z') { return false; } // skip the Z  	mSecondsSinceEpoch = seconds_since_epoch;  	return true; diff --git a/indra/llcommon/llerror.cpp b/indra/llcommon/llerror.cpp index bd334a6654..d06d6baf85 100644 --- a/indra/llcommon/llerror.cpp +++ b/indra/llcommon/llerror.cpp @@ -954,7 +954,12 @@ namespace LLError  		std::string class_name = className(site.mClassInfo);  		std::string function_name = functionName(site.mFunction); +#if LL_LINUX +		// gross, but typeid comparison seems to always fail here with gcc4.1 +		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name())) +#else  		if (site.mClassInfo != typeid(NoClassInfo)) +#endif // LL_LINUX  		{  			function_name = class_name + "::" + function_name;  		} @@ -1079,7 +1084,12 @@ namespace LLError  	#if LL_WINDOWS  		// DevStudio: __FUNCTION__ already includes the full class name  	#else +                #if LL_LINUX +		// gross, but typeid comparison seems to always fail here with gcc4.1 +		if (0 != strcmp(site.mClassInfo.name(), typeid(NoClassInfo).name())) +                #else  		if (site.mClassInfo != typeid(NoClassInfo)) +                #endif // LL_LINUX  		{  			prefix << className(site.mClassInfo) << "::";  		} @@ -1225,17 +1235,32 @@ namespace LLError  	char** LLCallStacks::sBuffer = NULL ;  	S32    LLCallStacks::sIndex  = 0 ; +#define SINGLE_THREADED 1 +  	class CallStacksLogLock  	{  	public:  		CallStacksLogLock();  		~CallStacksLogLock(); + +#if SINGLE_THREADED +		bool ok() const { return true; } +#else  		bool ok() const { return mOK; }  	private:  		bool mLocked;  		bool mOK; +#endif  	}; +#if SINGLE_THREADED +	CallStacksLogLock::CallStacksLogLock() +	{ +	} +	CallStacksLogLock::~CallStacksLogLock() +	{ +	} +#else  	CallStacksLogLock::CallStacksLogLock()  		: mLocked(false), mOK(false)  	{ @@ -1271,6 +1296,7 @@ namespace LLError  			apr_thread_mutex_unlock(gCallStacksLogMutexp);  		}  	} +#endif  	//static     void LLCallStacks::push(const char* function, const int line) diff --git a/indra/llcommon/llerror.h b/indra/llcommon/llerror.h index 09812de2b8..e64ee5e081 100644 --- a/indra/llcommon/llerror.h +++ b/indra/llcommon/llerror.h @@ -179,7 +179,7 @@ namespace LLError  		{ return s; }  		// used to indicate the end of a message -	class NoClassInfo { }; +	class LL_COMMON_API NoClassInfo { };  		// used to indicate no class info known for logging     //LLCallStacks keeps track of call stacks and output the call stacks to log file diff --git a/indra/llcommon/lleventtimer.cpp b/indra/llcommon/lleventtimer.cpp new file mode 100644 index 0000000000..d44e7ec1e6 --- /dev/null +++ b/indra/llcommon/lleventtimer.cpp @@ -0,0 +1,95 @@ +/**  + * @file lleventtimer.cpp + * @brief Cross-platform objects for doing timing  + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + *  + * Copyright (c) 2000-2009, 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 "lleventtimer.h" + +#include "u64.h" + + +////////////////////////////////////////////////////////////////////////////// +// +//		LLEventTimer Implementation +// +////////////////////////////////////////////////////////////////////////////// + +LLEventTimer::LLEventTimer(F32 period) +: mEventTimer() +{ +	mPeriod = period; +} + +LLEventTimer::LLEventTimer(const LLDate& time) +: mEventTimer() +{ +	mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); +} + + +LLEventTimer::~LLEventTimer() +{ +} + +//static +void LLEventTimer::updateClass()  +{ +	std::list<LLEventTimer*> completed_timers; + +	{ +		LLInstanceTrackerScopedGuard guard; +		for (instance_iter iter = guard.beginInstances(); iter != guard.endInstances(); )  +		{ +			LLEventTimer& timer = *iter++; +			F32 et = timer.mEventTimer.getElapsedTimeF32(); +			if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { +				timer.mEventTimer.reset(); +				if ( timer.tick() ) +				{ +					completed_timers.push_back( &timer ); +				} +			} +		} +	} + +	if ( completed_timers.size() > 0 ) +	{ +		for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();  +			 completed_iter != completed_timers.end();  +			 completed_iter++ )  +		{ +			delete *completed_iter; +		} +	} +} + + diff --git a/indra/llcommon/lleventtimer.h b/indra/llcommon/lleventtimer.h new file mode 100644 index 0000000000..5181cce52d --- /dev/null +++ b/indra/llcommon/lleventtimer.h @@ -0,0 +1,60 @@ +/**  + * @file lleventtimer.h + * @brief Cross-platform objects for doing timing  + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + *  + * Copyright (c) 2000-2009, 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$ + */ + +#ifndef LL_EVENTTIMER_H					 +#define LL_EVENTTIMER_H + +#include "stdtypes.h" +#include "lldate.h" +#include "llinstancetracker.h" +#include "lltimer.h" + +// class for scheduling a function to be called at a given frequency (approximate, inprecise) +class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer> +{ +public: +	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds +	LLEventTimer(const LLDate& time); +	virtual ~LLEventTimer(); +	 +	//function to be called at the supplied frequency +	// Normally return FALSE; TRUE will delete the timer after the function returns. +	virtual BOOL tick() = 0; + +	static void updateClass(); + +protected: +	LLTimer mEventTimer; +	F32 mPeriod; +}; + +#endif //LL_EVENTTIMER_H diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 48461df6ae..840d09d970 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -36,6 +36,10 @@  // pull in the actual class definition  #include "llfasttimer_class.h" +// +// Important note: These implementations must be FAST! +// +  #if LL_WINDOWS  //  // Windows implementation of CPU clock @@ -99,15 +103,17 @@ inline U64 LLFastTimer::getCPUClockCount64()  #endif -#if LL_LINUX || LL_SOLARIS +#if (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))  // -// Linux and Solaris implementation of CPU clock - all architectures. +// Linux and Solaris implementation of CPU clock - non-x86. +// This is accurate but SLOW!  Only use out of desperation.  //  // Try to use the MONOTONIC clock if available, this is a constant time counter -// with nanosecond resolution (but not necessarily accuracy) and attempts are made -// to synchronize this value between cores at kernel start. It should not be affected -// by CPU frequency. If not available use the REALTIME clock, but this may be affected by -// NTP adjustments or other user activity affecting the system time. +// with nanosecond resolution (but not necessarily accuracy) and attempts are +// made to synchronize this value between cores at kernel start. It should not +// be affected by CPU frequency. If not available use the REALTIME clock, but +// this may be affected by NTP adjustments or other user activity affecting +// the system time.  inline U64 LLFastTimer::getCPUClockCount64()  {  	struct timespec tp; @@ -124,12 +130,12 @@ inline U32 LLFastTimer::getCPUClockCount32()  {  	return (U32)(LLFastTimer::getCPUClockCount64() >> 8);  } -#endif // (LL_LINUX || LL_SOLARIS)) +#endif // (LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__)) -#if (LL_DARWIN) && (defined(__i386__) || defined(__amd64__)) +#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))  // -// Mac x86 implementation of CPU clock +// Mac+Linux+Solaris FAST x86 implementation of CPU clock  inline U32 LLFastTimer::getCPUClockCount32()  {  	U64 x; diff --git a/indra/llcommon/llfasttimer_class.cpp b/indra/llcommon/llfasttimer_class.cpp index 6d8d81e114..dfbae09864 100644 --- a/indra/llcommon/llfasttimer_class.cpp +++ b/indra/llcommon/llfasttimer_class.cpp @@ -218,9 +218,10 @@ LLFastTimer::DeclareTimer::DeclareTimer(const std::string& name)  // static  void LLFastTimer::DeclareTimer::updateCachedPointers()  { +	DeclareTimer::LLInstanceTrackerScopedGuard guard;  	// propagate frame state pointers to timer declarations -	for (DeclareTimer::instance_iter it = DeclareTimer::beginInstances(); -		it != DeclareTimer::endInstances(); +	for (DeclareTimer::instance_iter it = guard.beginInstances(); +		it != guard.endInstances();  		++it)  	{  		// update cached pointer @@ -229,17 +230,18 @@ void LLFastTimer::DeclareTimer::updateCachedPointers()  }  //static -#if LL_LINUX || LL_SOLARIS || ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__)) ) +#if (LL_DARWIN || LL_LINUX || LL_SOLARIS) && !(defined(__i386__) || defined(__amd64__))  U64 LLFastTimer::countsPerSecond() // counts per second for the *32-bit* timer  {  	return sClockResolution >> 8;  } -#else // windows or x86-mac +#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)); +	//getCPUFrequency returns MHz and sCPUClockFrequency wants to be in Hz +	static U64 sCPUClockFrequency = U64(LLProcessorInfo().getCPUFrequency()*1000000.0); -	// we drop the low-order byte in out timers, so report a lower frequency +	// we drop the low-order byte in our timers, so report a lower frequency  	return sCPUClockFrequency >> 8;  }  #endif @@ -371,20 +373,23 @@ void LLFastTimer::NamedTimer::buildHierarchy()  	if (sCurFrameIndex < 0 ) return;  	// set up initial tree -    for (instance_iter it = NamedTimer::beginInstances(); -		it != endInstances(); -		++it)  	{ -		NamedTimer& timer = *it; -		if (&timer == NamedTimerFactory::instance().getRootTimer()) continue; - -		// bootstrap tree construction by attaching to last timer to be on stack -		// when this timer was called -		if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer()) +		NamedTimer::LLInstanceTrackerScopedGuard guard; +		for (instance_iter it = guard.beginInstances(); +		     it != guard.endInstances(); +		     ++it)  		{ -			timer.setParent(timer.getFrameState().mLastCaller->mTimer); -			// no need to push up tree on first use, flag can be set spuriously -			timer.getFrameState().mMoveUpTree = false; +			NamedTimer& timer = *it; +			if (&timer == NamedTimerFactory::instance().getRootTimer()) continue; +			 +			// bootstrap tree construction by attaching to last timer to be on stack +			// when this timer was called +			if (timer.getFrameState().mLastCaller && timer.mParent == NamedTimerFactory::instance().getRootTimer()) +			{ +				timer.setParent(timer.getFrameState().mLastCaller->mTimer); +				// no need to push up tree on first use, flag can be set spuriously +				timer.getFrameState().mMoveUpTree = false; +			}  		}  	} @@ -486,18 +491,21 @@ void LLFastTimer::NamedTimer::resetFrame()  		F64 total_time = 0;  		LLSD sd; -		for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); -					it != NamedTimer::endInstances(); -					++it)  		{ -			NamedTimer& timer = *it; -			FrameState& info = timer.getFrameState(); -			sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);	 -			sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls; -			 -			// computing total time here because getting the root timer's getCountHistory -			// doesn't work correctly on the first frame -			total_time = total_time + info.mSelfTimeCounter * iclock_freq; +			NamedTimer::LLInstanceTrackerScopedGuard guard; +			for (NamedTimer::instance_iter it = guard.beginInstances(); +			     it != guard.endInstances(); +			     ++it) +			{ +				NamedTimer& timer = *it; +				FrameState& info = timer.getFrameState(); +				sd[timer.getName()]["Time"] = (LLSD::Real) (info.mSelfTimeCounter*iclock_freq);	 +				sd[timer.getName()]["Calls"] = (LLSD::Integer) info.mCalls; +				 +				// computing total time here because getting the root timer's getCountHistory +				// doesn't work correctly on the first frame +				total_time = total_time + info.mSelfTimeCounter * iclock_freq; +			}  		}  		sd["Total"]["Time"] = (LLSD::Real) total_time; @@ -531,21 +539,24 @@ void LLFastTimer::NamedTimer::resetFrame()  	DeclareTimer::updateCachedPointers();  	// reset for next frame -	for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); -		it != NamedTimer::endInstances(); -		++it)  	{ -		NamedTimer& timer = *it; - -		FrameState& info = timer.getFrameState(); -		info.mSelfTimeCounter = 0; -		info.mCalls = 0; -		info.mLastCaller = NULL; -		info.mMoveUpTree = false; -		// update parent pointer in timer state struct -		if (timer.mParent) +		NamedTimer::LLInstanceTrackerScopedGuard guard; +		for (NamedTimer::instance_iter it = guard.beginInstances(); +		     it != guard.endInstances(); +		     ++it)  		{ -			info.mParent = &timer.mParent->getFrameState(); +			NamedTimer& timer = *it; +			 +			FrameState& info = timer.getFrameState(); +			info.mSelfTimeCounter = 0; +			info.mCalls = 0; +			info.mLastCaller = NULL; +			info.mMoveUpTree = false; +			// update parent pointer in timer state struct +			if (timer.mParent) +			{ +				info.mParent = &timer.mParent->getFrameState(); +			}  		}  	} @@ -575,20 +586,23 @@ void LLFastTimer::NamedTimer::reset()  	}  	// reset all history -	for (NamedTimer::instance_iter it = NamedTimer::beginInstances(); -		it != NamedTimer::endInstances(); -		++it)  	{ -		NamedTimer& timer = *it; -		if (&timer != NamedTimerFactory::instance().getRootTimer())  +		NamedTimer::LLInstanceTrackerScopedGuard guard; +		for (NamedTimer::instance_iter it = guard.beginInstances(); +		     it != guard.endInstances(); +		     ++it)  		{ -			timer.setParent(NamedTimerFactory::instance().getRootTimer()); +			NamedTimer& timer = *it; +			if (&timer != NamedTimerFactory::instance().getRootTimer())  +			{ +				timer.setParent(NamedTimerFactory::instance().getRootTimer()); +			} +			 +			timer.mCountAverage = 0; +			timer.mCallAverage = 0; +			memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); +			memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);  		} - -		timer.mCountAverage = 0; -		timer.mCallAverage = 0; -		memset(timer.mCountHistory, 0, sizeof(U32) * HISTORY_NUM); -		memset(timer.mCallHistory, 0, sizeof(U32) * HISTORY_NUM);  	}  	sLastFrameIndex = 0; diff --git a/indra/llcommon/llinstancetracker.cpp b/indra/llcommon/llinstancetracker.cpp new file mode 100644 index 0000000000..c962cb5be1 --- /dev/null +++ b/indra/llcommon/llinstancetracker.cpp @@ -0,0 +1,20 @@ +/** + * @file   lllinstancetracker.cpp + *  + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * Copyright (c) 2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llinstancetracker.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +// llinstancetracker.h is presently header-only. This file exists only because our CMake +// test macro ADD_BUILD_TEST requires it. +int dummy = 0; diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h index 11fe523651..9df7998273 100644 --- a/indra/llcommon/llinstancetracker.h +++ b/indra/llcommon/llinstancetracker.h @@ -98,7 +98,10 @@ private:  		mKey = key;   		getMap_()[key] = static_cast<T*>(this);   	} -	void remove_() { getMap_().erase(mKey); } +	void remove_() +	{ +		getMap_().erase(mKey); +	}      static InstanceMap& getMap_()      { @@ -129,31 +132,65 @@ public:  	/// for completeness of analogy with the generic implementation  	static T* getInstance(T* k) { return k; } -	static key_iter beginKeys() { return getSet_().begin(); } -	static key_iter endKeys()   { return getSet_().end(); } -	static instance_iter beginInstances() { return instance_iter(getSet_().begin()); } -	static instance_iter endInstances()   { return instance_iter(getSet_().end()); }  	static S32 instanceCount() { return getSet_().size(); } +	// Instantiate this to get access to iterators for this type.  It's a 'guard' in the sense +	// that it treats deletes of this type as errors as long as there is an instance of +	// this class alive in scope somewhere (i.e. deleting while iterating is bad). +	class LLInstanceTrackerScopedGuard +	{ +	public: +		LLInstanceTrackerScopedGuard() +		{ +			++sIterationNestDepth; +		} + +		~LLInstanceTrackerScopedGuard() +		{ +			--sIterationNestDepth; +		} + +		static instance_iter beginInstances() {	return instance_iter(getSet_().begin()); } +		static instance_iter endInstances() { return instance_iter(getSet_().end()); } +		static key_iter beginKeys() { return getSet_().begin(); } +		static key_iter endKeys()   { return getSet_().end(); } +	}; +  protected: -	LLInstanceTracker() { getSet_().insert(static_cast<T*>(this)); } -	virtual ~LLInstanceTracker() { getSet_().erase(static_cast<T*>(this)); } +	LLInstanceTracker() +	{ +		// it's safe but unpredictable to create instances of this type while all instances are being iterated over.  I hate unpredictable.  This assert will probably be turned on early in the next development cycle. +		//llassert(sIterationNestDepth == 0); +		getSet_().insert(static_cast<T*>(this)); +	} +	virtual ~LLInstanceTracker() +	{ +		// it's unsafe to delete instances of this type while all instances are being iterated over. +		llassert(sIterationNestDepth == 0); +		getSet_().erase(static_cast<T*>(this)); +	} -	LLInstanceTracker(const LLInstanceTracker& other) { getSet_().insert(static_cast<T*>(this)); } +	LLInstanceTracker(const LLInstanceTracker& other) +	{ +		//llassert(sIterationNestDepth == 0); +		getSet_().insert(static_cast<T*>(this)); +	} -    static InstanceSet& getSet_()   // called after getReady() but before go() -    { -        if (! sInstances) -        { -            sInstances = new InstanceSet; -        } -        return *sInstances; -    } +	static InstanceSet& getSet_() +	{ +		if (! sInstances) +		{ +			sInstances = new InstanceSet; +		} +		return *sInstances; +	}  	static InstanceSet* sInstances; +	static S32 sIterationNestDepth;  };  template <typename T, typename KEY> typename LLInstanceTracker<T, KEY>::InstanceMap* LLInstanceTracker<T, KEY>::sInstances = NULL;  template <typename T> typename LLInstanceTracker<T, T*>::InstanceSet* LLInstanceTracker<T, T*>::sInstances = NULL; +template <typename T> S32 LLInstanceTracker<T, T*>::sIterationNestDepth = 0;  #endif diff --git a/indra/llcommon/lllivefile.cpp b/indra/llcommon/lllivefile.cpp index effda6c49c..5ca90d82ba 100644 --- a/indra/llcommon/lllivefile.cpp +++ b/indra/llcommon/lllivefile.cpp @@ -33,7 +33,7 @@  #include "lllivefile.h"  #include "llframetimer.h" -#include "lltimer.h" +#include "lleventtimer.h"  const F32 DEFAULT_CONFIG_FILE_REFRESH = 5.0f; diff --git a/indra/llcommon/llprocessor.cpp b/indra/llcommon/llprocessor.cpp index 8a4a4a8f9a..d3ba215751 100644 --- a/indra/llcommon/llprocessor.cpp +++ b/indra/llcommon/llprocessor.cpp @@ -30,130 +30,389 @@   * $/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> +#	define _interlockedbittestandset _renamed_interlockedbittestandset +#	define _interlockedbittestandreset _renamed_interlockedbittestandreset +#	include <intrin.h> +#	undef _interlockedbittestandset +#	undef _interlockedbittestandreset  #endif -#if !LL_DARWIN && !LL_SOLARIS - -#ifdef PROCESSOR_FREQUENCY_MEASURE_AVAILABLE -// We need the QueryPerformanceCounter and Sleep functions -#define FORCEINLINE __forceinline -#else -#define FORCEINLINE  +#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" +	}; + + + +	// *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 +	}; + +	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");  +	} -// Some macros we often need -//////////////////////////// -#define CheckBit(var, bit)   ((var & (1 << bit)) ? true : false) +	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)  { -#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 @@ -169,35 +428,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); @@ -210,2075 +461,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 -		if (CPUInfo.uiBrandID == 3 && CPUInfo.uiModel == 6) +		// __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); + +		// 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 -					{ -						strcpy(CPUInfo.strModel, "Intel Pentium 4 Willamette");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Willamette", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ -					} -					else							// else Xeon +				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 Xeon");		/* Flawfinder: ignore */ -						strncat(strCPUName, "Intel Pentium 4 Willamette Xeon", sizeof(strCPUName) - strlen(strCPUName) - 1);		/* Flawfinder: ignore */ +						setExtension(cpu_feature_names[index]);  					} -					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(); +		// 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); -	// And finally the processor configuration (caches, TLBs, ...) and translate -	// the data to readable strings -	GetStandardProcessorConfiguration(); -	TranslateProcessorConfiguration(); - -	// 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); - -	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; +	virtual ~LLProcessorInfoLinuxImpl() {} +private: -	// 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) -			{ -				DecodeProcessorConfiguration(ebxreg); -				DecodeProcessorConfiguration(ebxreg >> 8); -				DecodeProcessorConfiguration(ebxreg >> 16); -				DecodeProcessorConfiguration(ebxreg >> 24); -			} -			// And also the ecx register -			if ((ecxreg & 0x80000000) == 0) +			char line[MAX_STRING]; +			memset(line, 0, MAX_STRING); +			while(fgets(line, MAX_STRING, cpuinfo_fp))  			{ -				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); -} - -#elif LL_SOLARIS -#include <kstat.h> +		// setInfo(eExtendedModel, getSysctlInt("machdep.cpu.extmodel")); +		// setInfo(eBrandID, getSysctlInt("machdep.cpu.brand")); +		// setInfo(eType, 0); // ? where to find this? -#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 */ -	} -	// 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) -	{ -		// 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); - -	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 */ +# endif // LL_X86  	} -	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) +	std::string getCPUFeatureDescription() const   	{ -		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"); +		std::ostringstream s; -#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/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index 06ceeb2bc3..809a626c93 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -133,8 +133,11 @@ S32 LLQueuedThread::updateQueue(U32 max_time_ms)  	if (mThreaded)  	{  		pending = getPending(); +		if(pending > 0) +		{  		unpause();  	} +	}  	else  	{  		while (pending > 0) @@ -459,7 +462,7 @@ S32 LLQueuedThread::processNextRequest()  			req->setStatus(STATUS_QUEUED);  			mRequestQueue.insert(req);  			unlockData(); -			if (mThreaded && start_priority <= PRIORITY_LOW) +			if (mThreaded && start_priority < PRIORITY_NORMAL)  			{  				ms_sleep(1); // sleep the thread a little  			} diff --git a/indra/llcommon/llsdserialize_xml.cpp b/indra/llcommon/llsdserialize_xml.cpp index 7e1c2e35e0..fca173df47 100644 --- a/indra/llcommon/llsdserialize_xml.cpp +++ b/indra/llcommon/llsdserialize_xml.cpp @@ -139,12 +139,8 @@ S32 LLSDXMLFormatter::format_impl(const LLSD& data, std::ostream& ostr, U32 opti  	case LLSD::TypeBoolean:  		ostr << pre << "<boolean>";  		if(mBoolAlpha || -#if( LL_WINDOWS || __GNUC__ > 2)  		   (ostr.flags() & std::ios::boolalpha) -#else -		   (ostr.flags() & 0x0100) -#endif -			) +		   )  		{  			ostr << (data.asBoolean() ? "true" : "false");  		} @@ -511,12 +507,7 @@ void LLSDXMLParser::Impl::reset()  	mSkipping = false; -#if( LL_WINDOWS || __GNUC__ > 2)  	mCurrentKey.clear(); -#else -	mCurrentKey = std::string(); -#endif -  	XML_ParserReset(mParser, "utf-8");  	XML_SetUserData(mParser, this); @@ -644,11 +635,7 @@ void LLSDXMLParser::Impl::startElementHandler(const XML_Char* name, const XML_Ch  		LLSD& newElement = map[mCurrentKey];  		mStack.push_back(&newElement);		 -#if( LL_WINDOWS || __GNUC__ > 2)  		mCurrentKey.clear(); -#else -		mCurrentKey = std::string(); -#endif  	}  	else if (mStack.back()->isArray())  	{ diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 5f3d9d6582..f14d947734 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -676,6 +676,17 @@ long LLStringOps::sLocalTimeOffset = 0;  bool LLStringOps::sPacificDaylightTime = 0;  std::map<std::string, std::string> LLStringOps::datetimeToCodes; +std::vector<std::string> LLStringOps::sWeekDayList; +std::vector<std::string> LLStringOps::sWeekDayShortList; +std::vector<std::string> LLStringOps::sMonthList; +std::vector<std::string> LLStringOps::sMonthShortList; + + +std::string LLStringOps::sDayFormat; +std::string LLStringOps::sAM; +std::string LLStringOps::sPM; + +  S32	LLStringOps::collate(const llwchar* a, const llwchar* b)  {   	#if LL_WINDOWS @@ -724,6 +735,50 @@ void LLStringOps::setupDatetimeInfo (bool daylight)  	datetimeToCodes["timezone"]	= "%Z";		// PST  } +void tokenizeStringToArray(const std::string& data, std::vector<std::string>& output) +{ +	output.clear(); +	size_t length = data.size(); +	 +	// tokenize it and put it in the array +	std::string cur_word; +	for(size_t i = 0; i < length; ++i) +	{ +		if(data[i] == ':') +		{ +			output.push_back(cur_word); +			cur_word.clear(); +		} +		else +		{ +			cur_word.append(1, data[i]); +		} +	} +	output.push_back(cur_word); +} + +void LLStringOps::setupWeekDaysNames(const std::string& data) +{ +	tokenizeStringToArray(data,sWeekDayList); +} +void LLStringOps::setupWeekDaysShortNames(const std::string& data) +{ +	tokenizeStringToArray(data,sWeekDayShortList); +} +void LLStringOps::setupMonthNames(const std::string& data) +{ +	tokenizeStringToArray(data,sMonthList); +} +void LLStringOps::setupMonthShortNames(const std::string& data) +{ +	tokenizeStringToArray(data,sMonthShortList); +} +void LLStringOps::setupDayFormat(const std::string& data) +{ +	sDayFormat = data; +} + +  std::string LLStringOps::getDatetimeCode (std::string key)  {  	std::map<std::string, std::string>::iterator iter; @@ -819,6 +874,10 @@ namespace LLStringFn  //////////////////////////////////////////////////////////// +// Forward specialization of LLStringUtil::format before use in LLStringUtil::formatDatetime. +template<> +S32 LLStringUtil::format(std::string& s, const format_map_t& substitutions); +  //static  template<>   void LLStringUtil::getTokens(const std::string& instr, std::vector<std::string >& tokens, const std::string& delims) @@ -911,6 +970,20 @@ bool LLStringUtil::simpleReplacement(std::string &replacement, std::string token  	return false;  } +//static +template<> +void LLStringUtil::setLocale(std::string inLocale) +{ +	sLocale = inLocale; +}; + +//static +template<> +std::string LLStringUtil::getLocale(void) +{ +	return sLocale; +}; +  // static  template<>   void LLStringUtil::formatNumber(std::string& numStr, std::string decimals) @@ -984,7 +1057,53 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,  		}  		return true;  	} -	replacement = datetime.toHTTPDateString(code); + +	//EXT-7013 +	//few codes are not suppotred by strtime function (example - weekdays for Japanise) +	//so use predefined ones +	 +	//if sWeekDayList is not empty than current locale doesn't support +        //weekday name. +	time_t loc_seconds = (time_t) secFromEpoch; +	if(LLStringOps::sWeekDayList.size() == 7 && code == "%A") +	{ +		struct tm * gmt = gmtime (&loc_seconds); +		replacement = LLStringOps::sWeekDayList[gmt->tm_wday]; +	} +	else if(LLStringOps::sWeekDayShortList.size() == 7 && code == "%a") +	{ +		struct tm * gmt = gmtime (&loc_seconds); +		replacement = LLStringOps::sWeekDayShortList[gmt->tm_wday]; +	} +	else if(LLStringOps::sMonthList.size() == 12 && code == "%B") +	{ +		struct tm * gmt = gmtime (&loc_seconds); +		replacement = LLStringOps::sWeekDayList[gmt->tm_mon]; +	} +	else if( !LLStringOps::sDayFormat.empty() && code == "%d" ) +	{ +		struct tm * gmt = gmtime (&loc_seconds); +		LLStringUtil::format_map_t args; +		args["[MDAY]"] = llformat ("%d", gmt->tm_mday); +		replacement = LLStringOps::sDayFormat; +		LLStringUtil::format(replacement, args); +	} +	else if( !LLStringOps::sAM.empty() && !LLStringOps::sPM.empty() && code == "%p" ) +	{ +		struct tm * gmt = gmtime (&loc_seconds); +		if(gmt->tm_hour<12) +		{ +			replacement = LLStringOps::sAM; +		} +		else +		{ +			replacement = LLStringOps::sPM; +		} +	} +	else +	{ +		replacement = datetime.toHTTPDateString(code); +	}  	// *HACK: delete leading zero from hour string in case 'hour12' (code = %I) time format  	// to show time without leading zero, e.g. 08:16 -> 8:16 (EXT-2738). diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 62cedcde4e..8071c8aa2d 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -154,9 +154,19 @@ private:  	static long sPacificTimeOffset;  	static long sLocalTimeOffset;  	static bool sPacificDaylightTime; +  	static std::map<std::string, std::string> datetimeToCodes;  public: +	static std::vector<std::string> sWeekDayList; +	static std::vector<std::string> sWeekDayShortList; +	static std::vector<std::string> sMonthList; +	static std::vector<std::string> sMonthShortList; +	static std::string sDayFormat; + +	static std::string sAM; +	static std::string sPM; +  	static char toUpper(char elem) { return toupper((unsigned char)elem); }  	static llwchar toUpper(llwchar elem) { return towupper(elem); } @@ -185,6 +195,14 @@ public:  	static S32	collate(const llwchar* a, const llwchar* b);  	static void setupDatetimeInfo(bool pacific_daylight_time); + +	static void setupWeekDaysNames(const std::string& data); +	static void setupWeekDaysShortNames(const std::string& data); +	static void setupMonthNames(const std::string& data); +	static void setupMonthShortNames(const std::string& data); +	static void setupDayFormat(const std::string& data); + +  	static long getPacificTimeOffset(void) { return sPacificTimeOffset;}  	static long getLocalTimeOffset(void) { return sLocalTimeOffset;}  	// Is the Pacific time zone (aka server time zone) @@ -231,7 +249,7 @@ public:  	/////////////////////////////////////////////////////////////////////////////////////////  	// Static Utility functions that operate on std::strings -	static std::basic_string<T> null; +	static const std::basic_string<T> null;  	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;  	LL_COMMON_API static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims); @@ -241,8 +259,8 @@ public:  	LL_COMMON_API static S32 format(std::basic_string<T>& s, const LLSD& substitutions);  	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);  	LL_COMMON_API static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions); -	static void setLocale (std::string inLocale) {sLocale = inLocale;}; -	static std::string getLocale (void) {return sLocale;}; +	LL_COMMON_API static void setLocale (std::string inLocale); +	LL_COMMON_API static std::string getLocale (void);  	static bool isValidIndex(const std::basic_string<T>& string, size_type i)  	{ @@ -353,7 +371,7 @@ private:  	LL_COMMON_API static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);  }; -template<class T> std::basic_string<T> LLStringUtilBase<T>::null; +template<class T> const std::basic_string<T> LLStringUtilBase<T>::null;  template<class T> std::string LLStringUtilBase<T>::sLocale;  typedef LLStringUtilBase<char> LLStringUtil; diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 0272c55db2..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 = (S32)(proc.GetCPUFrequency(50)/1000000.0); -	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; -	if (200 < mCPUMhz && mCPUMhz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check +	out << proc.getCPUBrandName(); +	if (200 < mCPUMHz && mCPUMHz < 10000)           // *NOTE: cpu speed is often way wrong, do a sanity check  	{ -		out << " (" << mCPUMhz << " MHz)"; +		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 = (S32)llrint(mhz); -	} -	if (!cpuinfo["model name"].empty()) -		mCPUString = cpuinfo["model name"]; -# endif // LL_X86 -#endif // LL_LINUX  }  bool LLCPUInfo::hasAltivec() const @@ -595,9 +544,9 @@ bool LLCPUInfo::hasSSE2() const  	return mHasSSE2;  } -S32 LLCPUInfo::getMhz() const +F64 LLCPUInfo::getMHz() const  { -	return mCPUMhz; +	return mCPUMHz;  }  std::string LLCPUInfo::getCPUString() const @@ -607,44 +556,15 @@ 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;  	s << "->mHasSSE2:    " << (U32)mHasSSE2 << std::endl;  	s << "->mHasAltivec: " << (U32)mHasAltivec << std::endl; -	s << "->mCPUMhz:     " << mCPUMhz << std::endl; +	s << "->mCPUMHz:     " << mCPUMHz << std::endl;  	s << "->mCPUString:  " << mCPUString << std::endl;  } diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index c2c45bec9a..0b34951149 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -81,7 +81,7 @@ public:  	bool hasAltivec() const;  	bool hasSSE() const;  	bool hasSSE2() const; -	S32	 getMhz() const; +	F64 getMHz() const;  	// Family is "AMD Duron" or "Intel Pentium Pro"  	const std::string& getFamily() const { return mFamily; } @@ -90,7 +90,7 @@ private:  	bool mHasSSE;  	bool mHasSSE2;  	bool mHasAltivec; -	S32 mCPUMhz; +	F64 mCPUMHz;  	std::string mFamily;  	std::string mCPUString;  }; diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index adef1a9192..dbb8ec5231 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -135,7 +135,7 @@ class LL_COMMON_API LLMutex  {  public:  	LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex -	~LLMutex(); +	virtual ~LLMutex();  	void lock();		// blocks  	void unlock(); diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index 21e165ebc9..6111db2bfa 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -209,7 +209,7 @@ F64 calc_clock_frequency(U32 uiMeasureMSecs)  // Both Linux and Mac use gettimeofday for accurate time  F64 calc_clock_frequency(unsigned int uiMeasureMSecs)  { -	return 1000000.0; // microseconds, so 1 Mhz. +	return 1000000.0; // microseconds, so 1 MHz.  }  U64 get_clock_count() @@ -555,60 +555,3 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring)  } -////////////////////////////////////////////////////////////////////////////// -// -//		LLEventTimer Implementation -// -////////////////////////////////////////////////////////////////////////////// - -LLEventTimer::LLEventTimer(F32 period) -: mEventTimer() -{ -	mPeriod = period; -	mBusy = false; -} - -LLEventTimer::LLEventTimer(const LLDate& time) -: mEventTimer() -{ -	mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); -	mBusy = false; -} - - -LLEventTimer::~LLEventTimer() -{ -	llassert(!mBusy); // this LLEventTimer was destroyed from within its own tick() function - bad.  if you want tick() to cause destruction of its own timer, make it return true. -} - -//static -void LLEventTimer::updateClass()  -{ -	std::list<LLEventTimer*> completed_timers; -	for (instance_iter iter = beginInstances(); iter != endInstances(); )  -	{ -		LLEventTimer& timer = *iter++; -		F32 et = timer.mEventTimer.getElapsedTimeF32(); -		if (timer.mEventTimer.getStarted() && et > timer.mPeriod) { -			timer.mEventTimer.reset(); -			timer.mBusy = true; -			if ( timer.tick() ) -			{ -				completed_timers.push_back( &timer ); -			} -			timer.mBusy = false; -		} -	} - -	if ( completed_timers.size() > 0 ) -	{ -		for (std::list<LLEventTimer*>::iterator completed_iter = completed_timers.begin();  -			 completed_iter != completed_timers.end();  -			 completed_iter++ )  -		{ -			delete *completed_iter; -		} -	} -} - - diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index 4d995d5bba..baba95bfa1 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -39,8 +39,6 @@  #include <limits.h>  #include "stdtypes.h" -#include "lldate.h" -#include "llinstancetracker.h"  #include <string>  #include <list> @@ -171,26 +169,6 @@ LL_COMMON_API struct tm* utc_to_pacific_time(time_t utc_time, BOOL pacific_dayli  LL_COMMON_API void microsecondsToTimecodeString(U64 current_time, std::string& tcstring);  LL_COMMON_API void secondsToTimecodeString(F32 current_time, std::string& tcstring); -// class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LL_COMMON_API LLEventTimer : protected LLInstanceTracker<LLEventTimer> -{ -public: -	LLEventTimer(F32 period);	// period is the amount of time between each call to tick() in seconds -	LLEventTimer(const LLDate& time); -	virtual ~LLEventTimer(); -	 -	//function to be called at the supplied frequency -	// Normally return FALSE; TRUE will delete the timer after the function returns. -	virtual BOOL tick() = 0; - -	static void updateClass(); - -protected: -	LLTimer mEventTimer; -	F32 mPeriod; -	bool mBusy; -}; -  U64 LL_COMMON_API totalTime();					// Returns current system time in microseconds  #endif diff --git a/indra/llcommon/lluri.cpp b/indra/llcommon/lluri.cpp index 9d4f3a98f0..0e8f3f0f73 100644 --- a/indra/llcommon/lluri.cpp +++ b/indra/llcommon/lluri.cpp @@ -231,7 +231,8 @@ static BOOL isDefault(const std::string& scheme, U16 port)  void LLURI::parseAuthorityAndPathUsingOpaque()  {  	if (mScheme == "http" || mScheme == "https" || -		mScheme == "ftp" || mScheme == "secondlife" ) +		mScheme == "ftp" || mScheme == "secondlife" ||  +		mScheme == "x-grid-location-info")  	{  		if (mEscapedOpaque.substr(0,2) != "//")  		{ diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index bcbae06ec5..583c1e589b 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -33,9 +33,12 @@  // We can't use WIN32_LEAN_AND_MEAN here, needs lots of includes.  #if LL_WINDOWS -#	undef WIN32_LEAN_AND_MEAN -#	include <winsock2.h> -#	include <windows.h> +#undef WIN32_LEAN_AND_MEAN +#include <winsock2.h> +#include <windows.h> +// ugh, this is ugly.  We need to straighten out our linking for this library +#pragma comment(lib, "IPHLPAPI.lib") +#include <iphlpapi.h>  #endif  #include "lldefs.h" @@ -452,67 +455,102 @@ static void get_random_bytes(void *buf, int nbytes)  	return;	  } -#if LL_WINDOWS -typedef struct _ASTAT_ -{ -	ADAPTER_STATUS adapt; -	NAME_BUFFER    NameBuff [30]; -}ASTAT, * PASTAT; +#if	LL_WINDOWS +// Code	copied from	http://msdn.microsoft.com/en-us/library/aa365939(VS.85).aspx +// This	code grabs the first hardware	address, rather	than the first interface. +// Using a VPN can cause the first returned	interface	to be	changed. + +const	S32	MAC_ADDRESS_BYTES=6; +  // static -S32 LLUUID::getNodeID(unsigned char * node_id) -{ -	  ASTAT Adapter; -      NCB Ncb; -      UCHAR uRetCode; -      LANA_ENUM   lenum; -      int      i; -	  int retval = 0; - -      memset( &Ncb, 0, sizeof(Ncb) ); -      Ncb.ncb_command = NCBENUM; -      Ncb.ncb_buffer = (UCHAR *)&lenum; -      Ncb.ncb_length = sizeof(lenum); -      uRetCode = Netbios( &Ncb ); - //     printf( "The NCBENUM return code is: 0x%x \n", uRetCode ); - -      for(i=0; i < lenum.length ;i++) -      { -          memset( &Ncb, 0, sizeof(Ncb) ); -          Ncb.ncb_command = NCBRESET; -          Ncb.ncb_lana_num = lenum.lana[i]; - -          uRetCode = Netbios( &Ncb ); - //         printf( "The NCBRESET on LANA %d return code is: 0x%x \n", - //                 lenum.lana[i], uRetCode ); - -          memset( &Ncb, 0, sizeof (Ncb) ); -          Ncb.ncb_command = NCBASTAT; -          Ncb.ncb_lana_num = lenum.lana[i]; - -          strcpy( (char *)Ncb.ncb_callname,  "*              " );		/* Flawfinder: ignore */ -          Ncb.ncb_buffer = (unsigned char *)&Adapter; -          Ncb.ncb_length = sizeof(Adapter); - -          uRetCode = Netbios( &Ncb ); -//          printf( "The NCBASTAT on LANA %d return code is: 0x%x \n", -//                 lenum.lana[i], uRetCode ); -          if ( uRetCode == 0 ) -          { -//            printf( "The Ethernet Number on LANA %d is: %02x%02x%02x%02x%02x%02x\n", -//	 			  lenum.lana[i], -//                  Adapter.adapt.adapter_address[0], -//                  Adapter.adapt.adapter_address[1], -//                  Adapter.adapt.adapter_address[2], -//                  Adapter.adapt.adapter_address[3], -//                  Adapter.adapt.adapter_address[4], -//                  Adapter.adapt.adapter_address[5] ); -			memcpy(node_id,Adapter.adapt.adapter_address,6);		/* Flawfinder: ignore */ -			retval = 1; - -          } -	  } -	return retval; +S32	LLUUID::getNodeID(unsigned char	*node_id) +{ + +	// Declare and initialize variables. +	DWORD	dwSize = 0; +	DWORD	dwRetVal = 0; +	int	i; + +/* variables used	for	GetIfTable and GetIfEntry	*/ +	MIB_IFTABLE	*pIfTable; +	MIB_IFROW	*pIfRow; + +	// Allocate	memory for our pointers. +	pIfTable = (MIB_IFTABLE	*) malloc(sizeof (MIB_IFTABLE)); +	if (pIfTable ==	NULL)	 +	{ +			printf("Error allocating memory needed to call GetIfTable\n"); +			return 0; +	} + +	// Before	calling	GetIfEntry,	we call	GetIfTable to	make +	// sure	there	are	entries	to get and retrieve	the	interface	index. + +	// Make	an initial call	to GetIfTable	to get the +	// necessary size	into dwSize +	if (GetIfTable(pIfTable, &dwSize,	0) ==	ERROR_INSUFFICIENT_BUFFER) { +			free(pIfTable); +			pIfTable = (MIB_IFTABLE	*) malloc(dwSize); +			if (pIfTable ==	NULL)	 +			{ +					printf("Error	allocating memory\n"); +					return 0; +			} +	} +	//	Make a second	call to	GetIfTable to	get	the	actual +	// data	we want. +	if ((dwRetVal = GetIfTable(pIfTable, &dwSize,	0))	== NO_ERROR)  +	{ +		if (pIfTable->dwNumEntries > 0)	 +		{ +			pIfRow = (MIB_IFROW	*) malloc(sizeof (MIB_IFROW)); +			if (pIfRow ==	NULL)	 +			{ +					printf("Error allocating memory\n"); +					if (pIfTable != NULL)	 +					{ +						free(pIfTable); +						pIfTable = NULL; +					} +					return 0; +			} + +			int	limit	=	MAC_ADDRESS_BYTES; +			memcpy(node_id,	"\0\0\0\0\0\0",	limit);	// zero	out	array	of bytes	  +			for	(i = 0;	i < (int) pIfTable->dwNumEntries; i++)  +			{ +				pIfRow->dwIndex	= pIfTable->table[i].dwIndex; +				if ((dwRetVal = GetIfEntry(pIfRow)) == NO_ERROR)  +				{ +					switch (pIfRow->dwType)	 +					{ +						case IF_TYPE_ETHERNET_CSMACD: +						case IF_TYPE_IEEE80211:		  +							 limit = min((int) pIfRow->dwPhysAddrLen, limit); +							 if	(pIfRow->dwPhysAddrLen == 0) +									 break; +							 memcpy(node_id, (UCHAR *)&pIfRow->bPhysAddr[0], limit);		 //	just incase	the	PhysAddr is	not	the	expected MAC_Address size +							 free(pIfTable); +							 return 1;	//return first hardware	device found.	 +							break; + +						case IF_TYPE_OTHER: +						case IF_TYPE_PPP:										  +						case IF_TYPE_SOFTWARE_LOOPBACK:										  +						case IF_TYPE_ISO88025_TOKENRING:										 +						case IF_TYPE_IEEE1394:																		 +						case IF_TYPE_ATM:										  +						case IF_TYPE_TUNNEL:										 +								default: +									break; +					} +				} +			} +		} +	} +	free(pIfTable); +	return 0;  }  #elif LL_DARWIN diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index c78fb12018..3a0d66e4a5 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -133,6 +133,7 @@ public:  	U8 mData[UUID_BYTES];  }; +typedef std::vector<LLUUID> uuid_vec_t;  // Construct  inline LLUUID::LLUUID() diff --git a/indra/llcommon/llversionserver.h b/indra/llcommon/llversionserver.h index 0f1e59a18c..87fe7001e0 100644 --- a/indra/llcommon/llversionserver.h +++ b/indra/llcommon/llversionserver.h @@ -33,10 +33,10 @@  #ifndef LL_LLVERSIONSERVER_H  #define LL_LLVERSIONSERVER_H -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 31; +const S32 LL_VERSION_MAJOR = 2; +const S32 LL_VERSION_MINOR = 1;  const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 200030; +const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Server"; diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index 540aea4252..6e341b83a1 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -34,9 +34,9 @@  #define LL_LLVERSIONVIEWER_H  const S32 LL_VERSION_MAJOR = 2; -const S32 LL_VERSION_MINOR = 0; +const S32 LL_VERSION_MINOR = 1;  const S32 LL_VERSION_PATCH = 0; -const S32 LL_VERSION_BUILD = 200030; +const S32 LL_VERSION_BUILD = 0;  const char * const LL_CHANNEL = "Second Life Developer"; diff --git a/indra/llcommon/llworkerthread.cpp b/indra/llcommon/llworkerthread.cpp index 1b0e03cb2a..a29e9a348e 100644 --- a/indra/llcommon/llworkerthread.cpp +++ b/indra/llcommon/llworkerthread.cpp @@ -65,6 +65,27 @@ LLWorkerThread::~LLWorkerThread()  	// ~LLQueuedThread() will be called here  } +//called only in destructor. +void LLWorkerThread::clearDeleteList() +{ +	// Delete any workers in the delete queue (should be safe - had better be!) +	if (!mDeleteList.empty()) +	{ +		llwarns << "Worker Thread: " << mName << " destroyed with " << mDeleteList.size() +				<< " entries in delete list." << llendl; + +		mDeleteMutex->lock(); +		for (delete_list_t::iterator iter = mDeleteList.begin(); iter != mDeleteList.end(); ++iter) +		{ +			(*iter)->mRequestHandle = LLWorkerThread::nullHandle(); +			(*iter)->clearFlags(LLWorkerClass::WCF_HAVE_WORK); +			delete *iter ; +		} +		mDeleteList.clear() ; +		mDeleteMutex->unlock() ; +	} +} +  // virtual  S32 LLWorkerThread::update(U32 max_time_ms)  { @@ -320,7 +341,20 @@ bool LLWorkerClass::checkWork(bool aborting)  	if (mRequestHandle != LLWorkerThread::nullHandle())  	{  		LLWorkerThread::WorkRequest* workreq = (LLWorkerThread::WorkRequest*)mWorkerThread->getRequest(mRequestHandle); -		llassert_always(workreq); +		if(!workreq) +		{ +			if(mWorkerThread->isQuitting() || mWorkerThread->isStopped()) //the mWorkerThread is not running +			{ +				mRequestHandle = LLWorkerThread::nullHandle(); +				clearFlags(WCF_HAVE_WORK); +			} +			else +			{ +				llassert_always(workreq); +			} +			return true ; +		} +  		LLQueuedThread::status_t status = workreq->getStatus();  		if (status == LLWorkerThread::STATUS_ABORTED)  		{ @@ -370,7 +404,7 @@ void LLWorkerClass::scheduleDelete()  void LLWorkerClass::setPriority(U32 priority)  {  	mMutex.lock(); -	if (mRequestHandle != LLWorkerThread::nullHandle()) +	if (mRequestHandle != LLWorkerThread::nullHandle() && mRequestPriority != priority)  	{  		mRequestPriority = priority;  		mWorkerThread->setPriority(mRequestHandle, priority); diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h index a1e85d2ecc..1756ebab6b 100644 --- a/indra/llcommon/llworkerthread.h +++ b/indra/llcommon/llworkerthread.h @@ -80,6 +80,9 @@ public:  		S32 mParam;  	}; +protected: +	void clearDeleteList() ; +  private:  	typedef std::list<LLWorkerClass*> delete_list_t;  	delete_list_t mDeleteList; diff --git a/indra/llcommon/tests/llerror_test.cpp b/indra/llcommon/tests/llerror_test.cpp index 6785d0cf17..1558df231a 100644 --- a/indra/llcommon/tests/llerror_test.cpp +++ b/indra/llcommon/tests/llerror_test.cpp @@ -545,15 +545,6 @@ namespace tut  		// output order  	void ErrorTestObject::test<10>()  	{ -#if LL_LINUX -        skip("Fails on Linux, see comments"); -// on Linux: -// [error, 10] fail: 'order is time type location function message: expected -// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) : -// writeReturningLocationAndFunction: apple' actual -// '1947-07-08T03:04:05Z INFO: llcommon/tests/llerror_test.cpp(268) : -// LLError::NoClassInfo::writeReturningLocationAndFunction: apple'' -#endif  		LLError::setPrintLocation(true);  		LLError::setTimeFunction(roswell);  		mRecorder.setWantsTime(true); diff --git a/indra/llcommon/tests/llinstancetracker_test.cpp b/indra/llcommon/tests/llinstancetracker_test.cpp index 7415f2d33b..4bb3ec2922 100644 --- a/indra/llcommon/tests/llinstancetracker_test.cpp +++ b/indra/llcommon/tests/llinstancetracker_test.cpp @@ -138,23 +138,29 @@ namespace tut          keys.insert(&one);          keys.insert(&two);          keys.insert(&three); -        for (Unkeyed::key_iter ki(Unkeyed::beginKeys()), kend(Unkeyed::endKeys()); -             ki != kend; ++ki) -        { -            ensure_equals("spurious key", keys.erase(*ki), 1); -        } +	{ +		Unkeyed::LLInstanceTrackerScopedGuard guard; +		for (Unkeyed::key_iter ki(guard.beginKeys()), kend(guard.endKeys()); +		     ki != kend; ++ki) +		{ +			ensure_equals("spurious key", keys.erase(*ki), 1); +		} +	}          ensure_equals("unreported key", keys.size(), 0);          KeySet instances;          instances.insert(&one);          instances.insert(&two);          instances.insert(&three); -        for (Unkeyed::instance_iter ii(Unkeyed::beginInstances()), iend(Unkeyed::endInstances()); -             ii != iend; ++ii) -        { -            Unkeyed& ref = *ii; -            ensure_equals("spurious instance", instances.erase(&ref), 1); -        } +	{ +		Unkeyed::LLInstanceTrackerScopedGuard guard; +		for (Unkeyed::instance_iter ii(guard.beginInstances()), iend(guard.endInstances()); +		     ii != iend; ++ii) +		{ +			Unkeyed& ref = *ii; +			ensure_equals("spurious instance", instances.erase(&ref), 1); +		} +	}          ensure_equals("unreported instance", instances.size(), 0);      }  } // namespace tut 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); +	} +}  | 
