VirtualBox

Changeset 101848 in vbox


Ignore:
Timestamp:
Nov 6, 2023 9:44:58 AM (16 months ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
159944
Message:

libs/xpcom: Get rid of the memory flusher functionality which is not enabled in our builds, bugref:10545

Location:
trunk/src/libs/xpcom18a4/xpcom/base
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.cpp

    r1 r101848  
    4242#include "nsIObserverService.h"
    4343#include "nsAutoLock.h"
    44 #include "nsIThread.h"
    4544#include "nsIEventQueueService.h"
    4645#include "nsString.h"
    47 
    48 #if defined(XP_WIN)
    49 #include <windows.h>
    50 #define NS_MEMORY_FLUSHER_THREAD
    51 #elif defined(XP_MAC)
    52 #include <MacMemory.h>
    53 #define NS_MEMORY_FLUSHER_THREAD
    54 #else
    55 // Need to implement the nsIMemory::IsLowMemory() predicate
    56 #undef NS_MEMORY_FLUSHER_THREAD
    57 #endif
    58 
    59 //----------------------------------------------------------------------
    60 
    61 #if defined(XDEBUG_waterson)
    62 #define NS_TEST_MEMORY_FLUSHER
    63 #endif
    64 
    65 /**
    66  * A runnable that is used to periodically check the status
    67  * of the system, determine if too much memory is in use,
    68  * and if so, trigger a "memory flush".
    69  */
    70 class MemoryFlusher : public nsIRunnable
    71 {
    72 protected:
    73     nsMemoryImpl*  mMemoryImpl; // WEAK, it owns us.
    74     PRBool         mRunning;
    75     PRIntervalTime mTimeout;
    76     PRLock*        mLock;
    77     PRCondVar*     mCVar;
    78    
    79     MemoryFlusher(nsMemoryImpl* aMemoryImpl);
    80 
    81     enum {
    82         kInitialTimeout = 60 /*seconds*/
    83     };
    84 
    85 private:
    86     ~MemoryFlusher();
    87 
    88 public:
    89     /**
    90      * Create a memory flusher.
    91      * @param aResult the memory flusher
    92      * @param aMemoryImpl the owning nsMemoryImpl object
    93      * @return NS_OK if the memory flusher was created successfully
    94      */
    95     static nsresult
    96     Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl);
    97 
    98     NS_DECL_ISUPPORTS
    99     NS_DECL_NSIRUNNABLE
    100 
    101     /**
    102      * Stop the memory flusher.
    103      */
    104     nsresult Stop();
    105 };
    106 
    107 
    108 MemoryFlusher::MemoryFlusher(nsMemoryImpl* aMemoryImpl)
    109     : mMemoryImpl(aMemoryImpl),
    110       mRunning(PR_FALSE),
    111       mTimeout(PR_SecondsToInterval(kInitialTimeout)),
    112       mLock(nsnull),
    113       mCVar(nsnull)
    114 {
    115 }
    116 
    117 MemoryFlusher::~MemoryFlusher()
    118 {
    119     if (mLock)
    120         PR_DestroyLock(mLock);
    121 
    122     if (mCVar)
    123         PR_DestroyCondVar(mCVar);
    124 }
    125 
    126 
    127 nsresult
    128 MemoryFlusher::Create(MemoryFlusher** aResult, nsMemoryImpl* aMemoryImpl)
    129 {
    130     MemoryFlusher* result = new MemoryFlusher(aMemoryImpl);
    131     if (! result)
    132         return NS_ERROR_OUT_OF_MEMORY;
    133 
    134     do {
    135         if ((result->mLock = PR_NewLock()) == nsnull)
    136             break;
    137        
    138         if ((result->mCVar = PR_NewCondVar(result->mLock)) == nsnull)
    139             break;
    140 
    141         NS_ADDREF(*aResult = result);
    142         return NS_OK;
    143     } while (0);
    144 
    145     // Something bad happened if we get here...
    146     delete result;
    147     return NS_ERROR_OUT_OF_MEMORY;
    148 }
    149 
    150 NS_IMPL_THREADSAFE_ISUPPORTS1(MemoryFlusher, nsIRunnable)
    151 
    152 NS_IMETHODIMP
    153 MemoryFlusher::Run()
    154 {
    155     nsresult rv;
    156 
    157     mRunning = PR_TRUE;
    158 
    159     while (1) {
    160         PRStatus status;
    161 
    162         {
    163             nsAutoLock l(mLock);
    164             if (! mRunning) {
    165                 rv = NS_OK;
    166                 break;
    167             }
    168 
    169             status = PR_WaitCondVar(mCVar, mTimeout);
    170         }
    171 
    172         if (status != PR_SUCCESS) {
    173             rv = NS_ERROR_FAILURE;
    174             break;
    175         }
    176 
    177         if (! mRunning) {
    178             rv = NS_OK;
    179             break;
    180         }
    181 
    182         PRBool isLowMemory;
    183         rv = mMemoryImpl->IsLowMemory(&isLowMemory);
    184         if (NS_FAILED(rv))
    185             break;
    186 
    187 #ifdef NS_TEST_MEMORY_FLUSHER
    188         // Fire the flusher *every* time
    189         isLowMemory = PR_TRUE;
    190 #endif
    191 
    192         if (isLowMemory) {
    193             mMemoryImpl->FlushMemory(NS_LITERAL_STRING("low-memory").get(), PR_FALSE);
    194         }
    195     }
    196 
    197     mRunning = PR_FALSE;
    198 
    199     return rv;
    200 }
    201 
    202 
    203 nsresult
    204 MemoryFlusher::Stop()
    205 {
    206     if (mRunning) {
    207         nsAutoLock l(mLock);
    208         mRunning = PR_FALSE;
    209         PR_NotifyCondVar(mCVar);
    210     }
    211 
    212     return NS_OK;
    213 }
    214 
    215 //----------------------------------------------------------------------
    21646
    21747nsMemoryImpl* gMemory = nsnull;
     
    23868            break;
    23969
    240         rv = NS_ERROR_OUT_OF_MEMORY;
    241 
    242         mm->mFlushLock = PR_NewLock();
    243         if (! mm->mFlushLock)
    244             break;
    245 
    24670        rv = NS_OK;
    24771    } while (0);
     
    25579
    25680nsMemoryImpl::nsMemoryImpl()
    257     : mFlusher(nsnull),
    258       mFlushLock(nsnull),
    259       mIsFlushing(PR_FALSE)
    26081{
    26182}
     
    26384nsMemoryImpl::~nsMemoryImpl()
    26485{
    265     if (mFlushLock)
    266         PR_DestroyLock(mFlushLock);
    26786}
    268 
    269 ////////////////////////////////////////////////////////////////////////////////
    270 // Define NS_OUT_OF_MEMORY_TESTER if you want to force memory failures
    271 
    272 #ifdef DEBUG_xwarren
    273 #define NS_OUT_OF_MEMORY_TESTER
    274 #endif
    275 
    276 #ifdef NS_OUT_OF_MEMORY_TESTER
    277 
    278 // flush memory one in this number of times:
    279 #define NS_FLUSH_FREQUENCY        100000
    280 
    281 // fail allocation one in this number of flushes:
    282 #define NS_FAIL_FREQUENCY         10
    283 
    284 PRUint32 gFlushFreq = 0;
    285 PRUint32 gFailFreq = 0;
    286 
    287 static void*
    288 mallocator(PRSize size, PRUint32& counter, PRUint32 max)
    289 {
    290     if (counter++ >= max) {
    291         counter = 0;
    292         NS_ASSERTION(0, "about to fail allocation... watch out");
    293         return nsnull;
    294     }
    295     return PR_Malloc(size);
    296 }
    297 
    298 static void*
    299 reallocator(void* ptr, PRSize size, PRUint32& counter, PRUint32 max)
    300 {
    301     if (counter++ >= max) {
    302         counter = 0;
    303         NS_ASSERTION(0, "about to fail reallocation... watch out");
    304         return nsnull;
    305     }
    306     return PR_Realloc(ptr, size);
    307 }
    308 
    309 #define MALLOC1(s)       mallocator(s, gFlushFreq, NS_FLUSH_FREQUENCY)
    310 #define REALLOC1(p, s)   reallocator(p, s, gFlushFreq, NS_FLUSH_FREQUENCY)
    311 
    312 #else
    313 
    314 #define MALLOC1(s)       PR_Malloc(s)
    315 #define REALLOC1(p, s)   PR_Realloc(p, s)
    316 
    317 #endif // NS_OUT_OF_MEMORY_TESTER
    31887
    31988////////////////////////////////////////////////////////////////////////////////
     
    32392{
    32493    NS_ASSERTION(size, "nsMemoryImpl::Alloc of 0");
    325     void* result = MALLOC1(size);
    326     if (! result) {
    327         // Request an asynchronous flush
    328         FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
    329     }
     94    void* result = PR_Malloc(size);
    33095    return result;
    33196}
     
    33499nsMemoryImpl::Realloc(void * ptr, PRSize size)
    335100{
    336     void* result = REALLOC1(ptr, size);
    337     if (! result) {
    338         // Request an asynchronous flush
    339         FlushMemory(NS_LITERAL_STRING("alloc-failure").get(), PR_FALSE);
    340     }
     101    void* result = PR_Realloc(ptr, size);
    341102    return result;
    342103}
     
    351112nsMemoryImpl::HeapMinimize(PRBool aImmediate)
    352113{
    353     return FlushMemory(NS_LITERAL_STRING("heap-minimize").get(), aImmediate);
     114    return NS_OK;
    354115}
    355116
     
    357118nsMemoryImpl::IsLowMemory(PRBool *result)
    358119{
    359 #if defined(XP_WIN)
    360     MEMORYSTATUS stat;
    361     GlobalMemoryStatus(&stat);
    362     *result = ((float)stat.dwAvailPageFile / stat.dwTotalPageFile) < 0.1;
    363 #elif defined(XP_MAC)
    364 
    365   const long kReserveHeapFreeSpace = (256 * 1024);
    366   const long kReserveHeapContigSpace = (128 * 1024);
    367 
    368   long totalSpace, contiguousSpace;
    369   // this call measures how much memory would be available if the OS
    370   // purged. Despite the name, it does not purge (that happens
    371   // automatically when heap space is low).
    372   ::PurgeSpace(&totalSpace, &contiguousSpace);
    373   if (totalSpace < kReserveHeapFreeSpace || contiguousSpace < kReserveHeapContigSpace)
    374   {
    375     NS_WARNING("Found that heap mem is low");
    376     *result = PR_TRUE;
     120    *result = PR_FALSE;
    377121    return NS_OK;
    378   }
    379 
    380   // see how much temp mem is available (since our allocators allocate 1Mb chunks
    381   // in temp mem. We don't use TempMaxMem() (to get contig space) here, because it
    382   // compacts the application heap, so can be slow.
    383   const long kReserveTempFreeSpace = (2 * 1024 * 1024);     // 2Mb 
    384   long  totalTempSpace = ::TempFreeMem(); 
    385   if (totalTempSpace < kReserveTempFreeSpace)
    386   {
    387     NS_WARNING("Found that temp mem is low");
    388     *result = PR_TRUE;
    389     return NS_OK;
    390   } 
    391 
    392   *result = PR_FALSE;
    393  
    394 #else
    395     *result = PR_FALSE;
    396 #endif
    397     return NS_OK;
    398 }
    399 
    400 nsresult
    401 nsMemoryImpl::FlushMemory(const PRUnichar* aReason, PRBool aImmediate)
    402 {
    403     nsresult rv;
    404 
    405     if (aImmediate) {
    406         // They've asked us to run the flusher *immediately*. We've
    407         // got to be on the UI main thread for us to be able to do
    408         // that...are we?
    409         PRBool isOnUIThread = PR_FALSE;
    410 
    411         nsCOMPtr<nsIThread> main;
    412         rv = nsIThread::GetMainThread(getter_AddRefs(main));
    413         if (NS_SUCCEEDED(rv)) {
    414             nsCOMPtr<nsIThread> current;
    415             rv = nsIThread::GetCurrent(getter_AddRefs(current));
    416             if (NS_SUCCEEDED(rv)) {
    417                 if (current == main)
    418                     isOnUIThread = PR_TRUE;
    419             }
    420         }
    421 
    422         if (! isOnUIThread) {
    423             NS_ERROR("can't synchronously flush memory: not on UI thread");
    424             return NS_ERROR_FAILURE;
    425         }
    426     }
    427 
    428     {
    429         // Are we already flushing?
    430         nsAutoLock l(mFlushLock);
    431         if (mIsFlushing)
    432             return NS_OK;
    433 
    434         // Well, we are now!
    435         mIsFlushing = PR_TRUE;
    436     }
    437 
    438     // Run the flushers immediately if we can; otherwise, proxy to the
    439     // UI thread an run 'em asynchronously.
    440     if (aImmediate) {
    441         rv = RunFlushers(this, aReason);
    442     }
    443     else {
    444         nsCOMPtr<nsIEventQueueService> eqs = do_GetService(NS_EVENTQUEUESERVICE_CONTRACTID, &rv);
    445         if (eqs) {
    446             nsCOMPtr<nsIEventQueue> eq;
    447             rv = eqs->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eq));
    448             if (NS_SUCCEEDED(rv)) {
    449                 PL_InitEvent(&mFlushEvent.mEvent, this, HandleFlushEvent, DestroyFlushEvent);
    450                 mFlushEvent.mReason = aReason;
    451 
    452                 rv = eq->PostEvent(NS_REINTERPRET_CAST(PLEvent*, &mFlushEvent));
    453             }
    454         }
    455     }
    456 
    457     return rv;
    458 }
    459 
    460 nsresult
    461 nsMemoryImpl::RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason)
    462 {
    463     nsCOMPtr<nsIObserverService> os = do_GetService("@mozilla.org/observer-service;1");
    464     if (os) {
    465         os->NotifyObservers(aSelf, "memory-pressure", aReason);
    466     }
    467 
    468     {
    469         // Done flushing
    470         nsAutoLock l(aSelf->mFlushLock);
    471         aSelf->mIsFlushing = PR_FALSE;
    472     }
    473 
    474     return NS_OK;
    475 }
    476 
    477 void*
    478 nsMemoryImpl::HandleFlushEvent(PLEvent* aEvent)
    479 {
    480     nsMemoryImpl* self = NS_STATIC_CAST(nsMemoryImpl*, PL_GetEventOwner(aEvent));
    481     FlushEvent* event = NS_REINTERPRET_CAST(FlushEvent*, aEvent);
    482 
    483     RunFlushers(self, event->mReason);
    484     return 0;
    485 }
    486 
    487 void
    488 nsMemoryImpl::DestroyFlushEvent(PLEvent* aEvent)
    489 {
    490     // no-op, since mEvent is a member of nsMemoryImpl
    491122}
    492123
     
    507138        return NS_ERROR_FAILURE;
    508139
    509 #ifdef NS_MEMORY_FLUSHER_THREAD
    510     nsresult rv;
    511 
    512     // Create and start a memory flusher thread
    513     rv = MemoryFlusher::Create(&gMemory->mFlusher, gMemory);
    514     if (NS_FAILED(rv)) return rv;
    515 
    516     rv = NS_NewThread(getter_AddRefs(gMemory->mFlusherThread),
    517                       gMemory->mFlusher,
    518                       0, /* XXX use default stack size? */
    519                       PR_JOINABLE_THREAD);
    520 
    521     if (NS_FAILED(rv)) return rv;
    522 #endif
    523 
    524140    return NS_OK;
    525141}
     
    529145{
    530146    if (gMemory) {
    531 #ifdef NS_MEMORY_FLUSHER_THREAD
    532         if (gMemory->mFlusher) {
    533             // Stop the runnable...
    534             gMemory->mFlusher->Stop();
    535             NS_RELEASE(gMemory->mFlusher);
    536 
    537             // ...and wait for the thread to exit
    538             if (gMemory->mFlusherThread)
    539                 gMemory->mFlusherThread->Join();
    540         }
    541 #endif
    542 
    543147        NS_RELEASE(gMemory);
    544148        gMemory = nsnull;
  • trunk/src/libs/xpcom18a4/xpcom/base/nsMemoryImpl.h

    r1 r101848  
    4141#include "nsMemory.h"
    4242#include "nsISupportsArray.h"
    43 #include "nsIRunnable.h"
    44 #include "nsIThread.h"
    4543#include "nsCOMPtr.h"
    4644#include "plevent.h"
    47 
    48 struct PRLock;
    49 class MemoryFlusher;
    5045
    5146class nsMemoryImpl : public nsIMemory
     
    5651
    5752    nsMemoryImpl();
    58 
    59     nsresult FlushMemory(const PRUnichar* aReason, PRBool aImmediate);
    6053
    6154    // called from xpcom initialization/finalization:
     
    6861private:
    6962    ~nsMemoryImpl();
    70 
    71 protected:
    72     MemoryFlusher* mFlusher;
    73     nsCOMPtr<nsIThread> mFlusherThread;
    74 
    75     PRLock* mFlushLock;
    76     PRBool  mIsFlushing;
    77 
    78     struct FlushEvent {
    79         PLEvent mEvent;
    80         const PRUnichar* mReason;
    81     };
    82 
    83     FlushEvent mFlushEvent;
    84 
    85     static nsresult RunFlushers(nsMemoryImpl* aSelf, const PRUnichar* aReason);
    86 
    87     static void* PR_CALLBACK HandleFlushEvent(PLEvent* aEvent);
    88     static void  PR_CALLBACK DestroyFlushEvent(PLEvent* aEvent);
    8963};
    9064
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette