summaryrefslogtreecommitdiff
path: root/indra/newview/llappviewer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llappviewer.cpp')
-rw-r--r--indra/newview/llappviewer.cpp190
1 files changed, 134 insertions, 56 deletions
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index 6a808b5daf..4e1ef59765 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -686,7 +686,7 @@ LLAppViewer::~LLAppViewer()
}
bool LLAppViewer::init()
-{
+{
//
// Start of the application
//
@@ -719,6 +719,11 @@ bool LLAppViewer::init()
LL_INFOS("InitInfo") << "Configuration initialized." << LL_ENDL ;
+ //set the max heap size.
+ initMaxHeapSize() ;
+
+ LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled")) ;
+
// write Google Breakpad minidump files to our log directory
std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
logdir += gDirUtilp->getDirDelimiter();
@@ -781,6 +786,12 @@ bool LLAppViewer::init()
&LLUI::sGLScaleFactor);
LL_INFOS("InitInfo") << "UI initialized." << LL_ENDL ;
+ // Setup paths and LLTrans after LLUI::initClass has been called.
+ LLUI::setupPaths();
+ LLTransUtil::parseStrings("strings.xml", default_trans_args);
+ LLTransUtil::parseLanguageStrings("language_settings.xml");
+
+ // Setup notifications after LLUI::setupPaths() has been called.
LLNotifications::instance();
LL_INFOS("InitInfo") << "Notifications initialized." << LL_ENDL ;
@@ -826,12 +837,6 @@ bool LLAppViewer::init()
LLError::setPrintLocation(true);
}
-
- // Setup paths and LLTrans after LLUI::initClass has been called
- LLUI::setupPaths();
- LLTransUtil::parseStrings("strings.xml", default_trans_args);
- LLTransUtil::parseLanguageStrings("language_settings.xml");
-
// LLKeyboard relies on LLUI to know what some accelerator keys are called.
LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
@@ -1088,9 +1093,97 @@ bool LLAppViewer::init()
LLAgentLanguage::init();
+ return true;
+}
+
+void LLAppViewer::initMaxHeapSize()
+{
+ //set the max heap size.
+ //here is some info regarding to the max heap size:
+ //------------------------------------------------------------------------------------------
+ // OS | setting | SL address bits | max manageable memory space | max heap size
+ // Win 32 | default | 32-bit | 2GB | < 1.7GB
+ // Win 32 | /3G | 32-bit | 3GB | < 1.7GB or 2.7GB
+ //Linux 32 | default | 32-bit | 3GB | < 2.7GB
+ //Linux 32 |HUGEMEM | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 32-bit | 4GB | < 3.7GB
+ //64-bit OS |default | 64-bit | N/A (> 4GB) | N/A (> 4GB)
+ //------------------------------------------------------------------------------------------
+ //currently SL is built under 32-bit setting, we set its max heap size no more than 1.6 GB.
+
+ //F32 max_heap_size_gb = llmin(1.6f, (F32)gSavedSettings.getF32("MaxHeapSize")) ;
+ F32 max_heap_size_gb = gSavedSettings.getF32("MaxHeapSize") ;
+ BOOL enable_mem_failure_prevention = (BOOL)gSavedSettings.getBOOL("MemoryFailurePreventionEnabled") ;
+
+ LLMemory::initMaxHeapSizeGB(max_heap_size_gb, enable_mem_failure_prevention) ;
+}
+void LLAppViewer::checkMemory()
+{
+ const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
+ //const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
+ const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+ //static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
+ static void* last_reserved_address = NULL ;
- return true;
+ if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
+ {
+ return ;
+ }
+ mMemCheckTimer.reset() ;
+
+ if(gGLManager.mDebugGPU)
+ {
+ //update the availability of memory
+ LLMemory::updateMemoryInfo() ;
+ }
+
+ //check the virtual address space fragmentation
+ if(!last_reserved_address)
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ }
+ else
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ if(!last_reserved_address) //failed, try once more
+ {
+ last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+ }
+ }
+
+ S32 is_low = !last_reserved_address || LLMemory::isMemoryPoolLow() ;
+
+ //if(is_low < 0) //to force quit
+ //{
+ // if(force_quit_timer > MAX_QUIT_WAIT_TIME) //just hit the limit for the first time
+ // {
+ // //send out the notification to tell the viewer is about to quit in 30 seconds.
+ // LLNotification::Params params("ForceQuitDueToLowMemory");
+ // LLNotifications::instance().add(params);
+
+ // force_quit_timer = MAX_QUIT_WAIT_TIME - MEMORY_CHECK_INTERVAL ;
+ // }
+ // else
+ // {
+ // force_quit_timer -= MEMORY_CHECK_INTERVAL ;
+ // if(force_quit_timer < 0.f)
+ // {
+ // forceQuit() ; //quit
+ // }
+ // }
+ //}
+ //else
+ //{
+ // force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
+ //}
+
+ LLPipeline::throttleNewMemoryAllocation(!is_low ? FALSE : TRUE) ;
+
+ if(is_low)
+ {
+ LLMemory::logMemoryInfo() ;
+ }
}
static LLFastTimer::DeclareTimer FTM_MESSAGES("System Messages");
@@ -1118,7 +1211,7 @@ bool LLAppViewer::mainLoop()
//-------------------------------------------
// Create IO Pump to use for HTTP Requests.
- gServicePump = new LLPumpIO(gAPRPoolp);
+ gServicePump = new LLPumpIO;
LLHTTPClient::setPump(*gServicePump);
LLCurl::setCAFile(gDirUtilp->getCAFile());
@@ -1128,7 +1221,6 @@ bool LLAppViewer::mainLoop()
LLVoiceClient::getInstance()->init(gServicePump);
LLTimer frameTimer,idleTimer;
LLTimer debugTime;
- LLFrameTimer memCheckTimer;
LLViewerJoystick* joystick(LLViewerJoystick::getInstance());
joystick->setNeedsReset(true);
@@ -1139,7 +1231,9 @@ bool LLAppViewer::mainLoop()
// point of posting.
LLSD newFrame;
- const F32 memory_check_interval = 1.0f ; //second
+ //LLPrivateMemoryPoolTester::getInstance()->run(false) ;
+ //LLPrivateMemoryPoolTester::getInstance()->run(true) ;
+ //LLPrivateMemoryPoolTester::destroy() ;
// Handle messages
while (!LLApp::isExiting())
@@ -1150,18 +1244,8 @@ bool LLAppViewer::mainLoop()
llclearcallstacks;
//check memory availability information
- {
- if(memory_check_interval < memCheckTimer.getElapsedTimeF32())
- {
- memCheckTimer.reset() ;
-
- //update the availability of memory
- LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
- }
- llcallstacks << "Available physical mem(KB): " << mAvailPhysicalMemInKB << llcallstacksendl ;
- llcallstacks << "Available virtual mem(KB): " << mAvailVirtualMemInKB << llcallstacksendl ;
- }
-
+ checkMemory() ;
+
try
{
pingMainloopTimeout("Main:MiscNativeWindowEvents");
@@ -1325,7 +1409,7 @@ bool LLAppViewer::mainLoop()
idleTimer.reset();
bool is_slow = (frameTimer.getElapsedTimeF64() > FRAME_SLOW_THRESHOLD) ;
S32 total_work_pending = 0;
- S32 total_io_pending = 0;
+ S32 total_io_pending = 0;
while(!is_slow)//do not unpause threads if the frame rates are very low.
{
S32 work_pending = 0;
@@ -1393,15 +1477,7 @@ bool LLAppViewer::mainLoop()
}
catch(std::bad_alloc)
{
- {
- llinfos << "Availabe physical memory(KB) at the beginning of the frame: " << mAvailPhysicalMemInKB << llendl ;
- llinfos << "Availabe virtual memory(KB) at the beginning of the frame: " << mAvailVirtualMemInKB << llendl ;
-
- LLMemoryInfo::getAvailableMemoryKB(mAvailPhysicalMemInKB, mAvailVirtualMemInKB) ;
-
- llinfos << "Current availabe physical memory(KB): " << mAvailPhysicalMemInKB << llendl ;
- llinfos << "Current availabe virtual memory(KB): " << mAvailVirtualMemInKB << llendl ;
- }
+ LLMemory::logMemoryInfo(TRUE) ;
//stop memory leaking simulation
LLFloaterMemLeak* mem_leak_instance =
@@ -1494,16 +1570,16 @@ bool LLAppViewer::cleanup()
}
// *TODO - generalize this and move DSO wrangling to a helper class -brad
- std::set<struct apr_dso_handle_t *>::const_iterator i;
- for(i = mPlugins.begin(); i != mPlugins.end(); ++i)
+ for(std::map<apr_dso_handle_t*, boost::shared_ptr<LLAPRPool> >::iterator plugin = mPlugins.begin();
+ plugin != mPlugins.end(); ++plugin)
{
int (*ll_plugin_stop_func)(void) = NULL;
- apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, *i, "ll_plugin_stop");
+ apr_status_t rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll_plugin_stop_func, plugin->first, "ll_plugin_stop");
ll_plugin_stop_func();
- rv = apr_dso_unload(*i);
+ rv = apr_dso_unload(plugin->first);
}
- mPlugins.clear();
+ mPlugins.clear(); // Forget handles and destroy all memory pools.
//flag all elements as needing to be destroyed immediately
// to ensure shutdown order
@@ -1887,6 +1963,9 @@ bool LLAppViewer::cleanup()
LLMainLoopRepeater::instance().stop();
+ //release all private memory pools.
+ LLPrivateMemoryPoolManager::destroyClass() ;
+
ll_close_fail_log();
MEM_TRACK_RELEASE
@@ -1938,7 +2017,7 @@ bool LLAppViewer::initThreads()
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
{
- LLFastTimer::sLogLock = new LLMutex(NULL);
+ LLFastTimer::sLogLock = new LLMutex;
mFastTimerLogThread = new LLFastTimerLogThread(LLFastTimer::sLogName);
mFastTimerLogThread->start();
}
@@ -3186,8 +3265,7 @@ void LLAppViewer::handleViewerCrash()
else crash_file_name = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,ERROR_MARKER_FILE_NAME);
llinfos << "Creating crash marker file " << crash_file_name << llendl;
- LLAPRFile crash_file ;
- crash_file.open(crash_file_name, LL_APR_W);
+ LLAPRFile crash_file(crash_file_name, LL_APR_W);
if (crash_file.getFileHandle())
{
LL_INFOS("MarkerFile") << "Created crash marker file " << crash_file_name << LL_ENDL;
@@ -3251,11 +3329,10 @@ bool LLAppViewer::anotherInstanceRunning()
LL_DEBUGS("MarkerFile") << "Checking marker file for lock..." << LL_ENDL;
//Freeze case checks
- if (LLAPRFile::isExist(marker_file, NULL, LL_APR_RB))
+ if (LLAPRFile::isExist(marker_file, LL_APR_RB))
{
// File exists, try opening with write permissions
- LLAPRFile outfile ;
- outfile.open(marker_file, LL_APR_WB);
+ LLAPRFile outfile(marker_file, LL_APR_WB);
apr_file_t* fMarker = outfile.getFileHandle() ;
if (!fMarker)
{
@@ -3294,25 +3371,25 @@ void LLAppViewer::initMarkerFile()
std::string llerror_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, LLERROR_MARKER_FILE_NAME);
std::string error_marker_file = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, ERROR_MARKER_FILE_NAME);
- if (LLAPRFile::isExist(mMarkerFileName, NULL, LL_APR_RB) && !anotherInstanceRunning())
+ if (LLAPRFile::isExist(mMarkerFileName, LL_APR_RB) && !anotherInstanceRunning())
{
gLastExecEvent = LAST_EXEC_FROZE;
LL_INFOS("MarkerFile") << "Exec marker found: program froze on previous execution" << LL_ENDL;
}
- if(LLAPRFile::isExist(logout_marker_file, NULL, LL_APR_RB))
+ if(LLAPRFile::isExist(logout_marker_file, LL_APR_RB))
{
gLastExecEvent = LAST_EXEC_LOGOUT_FROZE;
LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
LLAPRFile::remove(logout_marker_file);
}
- if(LLAPRFile::isExist(llerror_marker_file, NULL, LL_APR_RB))
+ if(LLAPRFile::isExist(llerror_marker_file, LL_APR_RB))
{
if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
else gLastExecEvent = LAST_EXEC_LLERROR_CRASH;
LL_INFOS("MarkerFile") << "Last exec LLError crashed, setting LastExecEvent to " << gLastExecEvent << LL_ENDL;
LLAPRFile::remove(llerror_marker_file);
}
- if(LLAPRFile::isExist(error_marker_file, NULL, LL_APR_RB))
+ if(LLAPRFile::isExist(error_marker_file, LL_APR_RB))
{
if(gLastExecEvent == LAST_EXEC_LOGOUT_FROZE) gLastExecEvent = LAST_EXEC_LOGOUT_CRASH;
else gLastExecEvent = LAST_EXEC_OTHER_CRASH;
@@ -3328,7 +3405,7 @@ void LLAppViewer::initMarkerFile()
// Create the marker file for this execution & lock it
apr_status_t s;
- s = mMarkerFile.open(mMarkerFileName, LL_APR_W, TRUE);
+ s = mMarkerFile.open(mMarkerFileName, LL_APR_W, LLAPRFile::long_lived);
if (s == APR_SUCCESS && mMarkerFile.getFileHandle())
{
@@ -4586,8 +4663,7 @@ void LLAppViewer::sendLogoutRequest()
gLogoutInProgress = TRUE;
mLogoutMarkerFileName = gDirUtilp->getExpandedFilename(LL_PATH_LOGS,LOGOUT_MARKER_FILE_NAME);
- LLAPRFile outfile ;
- outfile.open(mLogoutMarkerFileName, LL_APR_W);
+ LLAPRFile outfile(mLogoutMarkerFileName, LL_APR_W);
mLogoutMarkerFile = outfile.getFileHandle() ;
if (mLogoutMarkerFile)
{
@@ -5039,14 +5115,15 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
}
#endif // LL_WINDOWS
- apr_dso_handle_t * eventhost_dso_handle = NULL;
- apr_pool_t * eventhost_dso_memory_pool = NULL;
+ boost::shared_ptr<LLAPRPool> eventhost_dso_memory_pool_ptr(new LLAPRPool);
+ LLAPRPool& eventhost_dso_memory_pool(*eventhost_dso_memory_pool_ptr);
+ apr_dso_handle_t* eventhost_dso_handle = NULL;
//attempt to load the shared library
- apr_pool_create(&eventhost_dso_memory_pool, NULL);
+ eventhost_dso_memory_pool.create();
apr_status_t rv = apr_dso_load(&eventhost_dso_handle,
dso_path.c_str(),
- eventhost_dso_memory_pool);
+ eventhost_dso_memory_pool());
llassert_always(! ll_apr_warn_status(rv, eventhost_dso_handle));
llassert_always(eventhost_dso_handle != NULL);
@@ -5066,7 +5143,8 @@ void LLAppViewer::loadEventHostModule(S32 listen_port)
llerrs << "problem loading eventhost plugin, status: " << status << llendl;
}
- mPlugins.insert(eventhost_dso_handle);
+ // Store the handle and link it to the pool that was used to allocate it.
+ mPlugins[eventhost_dso_handle] = eventhost_dso_memory_pool_ptr;
}
void LLAppViewer::launchUpdater()