Fix a race condition in RosAlloc.

Fix a race condition in RosAlloc between RosAlloc::BulkFree() and
RosAlloc::RevokeThreadLocalRuns() with regard to bulk_free_bit_map.

Change-Id: I128917d5bdfe2dab604174ca4cbe228282578b8a
Signed-off-by: Serguei Katkov <serguei.i.katkov@intel.com>
Bug: 12592026
diff --git a/runtime/gc/allocator/rosalloc.cc b/runtime/gc/allocator/rosalloc.cc
index 8ae61a3..6c9e6f2 100644
--- a/runtime/gc/allocator/rosalloc.cc
+++ b/runtime/gc/allocator/rosalloc.cc
@@ -904,7 +904,7 @@
     uint32_t from_vec = *from_vecp;
     if (from_vec != 0) {
       *to_vecp |= from_vec;
-      *from_vecp = 0;  // clear the from free bit map.
+      *from_vecp = 0;  // clear the bulk free bit map.
     }
     DCHECK_EQ(*from_vecp, static_cast<uint32_t>(0));
   }
@@ -1468,6 +1468,8 @@
 
 void RosAlloc::RevokeThreadLocalRuns(Thread* thread) {
   Thread* self = Thread::Current();
+  // Avoid race conditions on the bulk free bit maps with BulkFree() (GC).
+  WriterMutexLock wmu(self, bulk_free_lock_);
   for (size_t idx = 0; idx < kNumOfSizeBrackets; idx++) {
     MutexLock mu(self, *size_bracket_locks_[idx]);
     Run* thread_local_run = reinterpret_cast<Run*>(thread->rosalloc_runs_[idx]);
diff --git a/runtime/gc/allocator/rosalloc.h b/runtime/gc/allocator/rosalloc.h
index 4eb13315..7480975 100644
--- a/runtime/gc/allocator/rosalloc.h
+++ b/runtime/gc/allocator/rosalloc.h
@@ -456,7 +456,9 @@
   // and the footprint.
   Mutex lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
   // The reader-writer lock to allow one bulk free at a time while
-  // allowing multiple individual frees at the same time.
+  // allowing multiple individual frees at the same time. Also, this
+  // is used to avoid race conditions between BulkFree() and
+  // RevokeThreadLocalRuns() on the bulk free bitmaps.
   ReaderWriterMutex bulk_free_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
 
   // The page release mode.