OSDN Git Service

Do not initiate a concurrent collection if one is already running.
authorCarl Shapiro <cshapiro@google.com>
Fri, 10 Jun 2011 06:45:49 +0000 (23:45 -0700)
committerCarl Shapiro <cshapiro@google.com>
Fri, 10 Jun 2011 06:45:55 +0000 (23:45 -0700)
It is possible to cause a recursive garbage collection by writing a
program that triggers a concurrent garbage collection and initiates a
concurrent garbage collection before the garbage collection thread is
scheduled.  For example

  for (;;) { new byte[16 << 20]; System.gc(); }

When this condition occurs a warning is logged although such warnings
ought to be upgraded to fatal errors.  With this change, when the
garbage collection thread is scheduled it first checks to see if there
is a running collection before calling down to start the collection.

Change-Id: Ia7baf5eba245bbf3fe053d3bad3f90876cad2459

vm/alloc/HeapSource.cpp

index aa084ab..fd2d46c 100644 (file)
@@ -401,9 +401,16 @@ static void *gcDaemonThread(void* arg)
     while (gHs->gcThreadShutdown != true) {
         dvmWaitCond(&gHs->gcThreadCond, &gHs->gcThreadMutex);
         dvmLockHeap();
-        dvmChangeStatus(NULL, THREAD_RUNNING);
-        dvmCollectGarbageInternal(GC_CONCURRENT);
-        dvmChangeStatus(NULL, THREAD_VMWAIT);
+        /*
+         * Another thread may have started a concurrent garbage
+         * collection before we were scheduled.  Check for this
+         * condition before proceeding.
+         */
+        if (!gDvm.gcHeap->gcRunning) {
+            dvmChangeStatus(NULL, THREAD_RUNNING);
+            dvmCollectGarbageInternal(GC_CONCURRENT);
+            dvmChangeStatus(NULL, THREAD_VMWAIT);
+        }
         dvmUnlockHeap();
     }
     dvmChangeStatus(NULL, THREAD_RUNNING);