Retry mmap if it fails

Sometimes, mmap returns ENOMEM even though there is enough memory, in
that case, retried mmap mostly succeeds.

So as a workaround, let MemMapArena::Allocate retry at most 3 time.
(to resolve flaky build failure)

Bug: 278665389
Test: run dex2oat repeatedly
Change-Id: Icbde6a06fe8d1b189486ea2ab10003425248df52
diff --git a/runtime/base/mem_map_arena_pool.cc b/runtime/base/mem_map_arena_pool.cc
index ae7db45..fc1a61e 100644
--- a/runtime/base/mem_map_arena_pool.cc
+++ b/runtime/base/mem_map_arena_pool.cc
@@ -57,13 +57,24 @@
   // and we want to be able to use all memory that we actually allocate.
   size = RoundUp(size, kPageSize);
   std::string error_msg;
-  MemMap map = MemMap::MapAnonymous(name,
-                                    size,
-                                    PROT_READ | PROT_WRITE,
-                                    low_4gb,
-                                    &error_msg);
-  CHECK(map.IsValid()) << error_msg;
-  return map;
+  // TODO(b/278665389): remove this retry logic if the root cause is found.
+  constexpr int MAX_RETRY_CNT = 3;
+  int retry_cnt = 0;
+  while (true) {
+    MemMap map = MemMap::MapAnonymous(name, size, PROT_READ | PROT_WRITE, low_4gb, &error_msg);
+    if (map.IsValid()) {
+      if (retry_cnt > 0) {
+        LOG(WARNING) << "Succeed with retry(cnt=" << retry_cnt << ")";
+      }
+      return map;
+    } else {
+      if (retry_cnt == MAX_RETRY_CNT) {
+        CHECK(map.IsValid()) << error_msg << "(retried " << retry_cnt << " times)";
+      }
+    }
+    retry_cnt++;
+    LOG(ERROR) << error_msg << " but retry(cnt=" << retry_cnt << ")";
+  }
 }
 
 MemMapArena::~MemMapArena() {