< prev index next >

src/share/vm/runtime/os.cpp

Print this page
rev 7280 : 8064457: Introduce compressed oops mode "disjoint base" and improve compressed heap handling.

@@ -1531,10 +1531,119 @@
     MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
   }
   return result;
 }
 
+// A convenience function which attempts to reserve memory at a number
+// of given addresses. An address array is given and first the first,
+// then the second is tried and so on.
+// Function returns NULL if memory could not be obtained at any of the
+// given addresses.
+//
+// parameters
+// bytes - size of block
+// addr  - array of addresses, NULL terminated
+//
+char* os::attempt_reserve_memory_at_multiple(size_t bytes, char* addr[]) {
+  for (int i = 0; addr[i]; i ++) {
+    char* const attach_point = addr[i];
+    assert(attach_point >= (char *)HeapBaseMinAddress, "Flag support broken");
+    char* const addr = os::attempt_reserve_memory_at(bytes, attach_point);
+    if (addr) {
+      // Note: depending on platform and OS, it is not guaranteed that
+      //  os::attempt_reserve_memory_at only returns requested addr or nothing :/
+      if (addr != attach_point) {
+        os::release_memory(addr, bytes);
+      } else {
+        return addr;
+      }
+    }
+  }
+
+  return NULL;
+}
+
+// A convenience function which attempts to reserve memory
+// in a given memory range.
+char* os::attempt_reserve_memory_in_range(size_t size, size_t alignment,
+                                          char* range_from, char* range_to, int num_attempts) {
+  // sanity checks
+  if (range_from == 0) {
+    range_from = (char*) 1;
+  }
+
+  if (size == 0) {
+    return NULL;
+  }
+
+  if (range_to <= range_from) {
+    return NULL;
+  } else {
+    size_t d = range_to - range_from;
+    if (d < size) {
+      return NULL;
+    }
+  }
+
+  // The necessary attach point alignment (for mmap or shmat to have a
+  // chance of attaching).
+  const size_t os_attach_point_alignment =
+    AIX_ONLY(SIZE_256M)  // Known shm boundary alignment.
+    NOT_AIX(os::vm_allocation_granularity());
+
+  const size_t attach_point_alignment =
+    alignment > 0 ?
+    lcm(alignment, os_attach_point_alignment) : os_attach_point_alignment;
+
+  // Calc address range within we try to attach (range of possible start addresses).
+  char* const highest_start = (char *)align_ptr_down(range_to - size, attach_point_alignment);
+  char* const lowest_start  = (char *)align_ptr_up(range_from, attach_point_alignment);
+  const size_t attach_range = highest_start - lowest_start;
+
+  // Default is 20  ...
+  if (num_attempts <= 0) {
+    num_attempts = 20;
+  }
+
+  // ... but cap at possible
+  const uint64_t num_attempts_possible =
+    (attach_range / attach_point_alignment) + 1; // at least one is possible even for 0 sized attach range
+
+  if (num_attempts_possible < (uint64_t)num_attempts) {
+    num_attempts = num_attempts_possible;
+  }
+
+  const size_t stepsize =
+    align_size_up(attach_range / num_attempts, attach_point_alignment);
+
+  // Build up attach point array.
+  char** attach_points = (char**) os::malloc((num_attempts + 1) * sizeof(char*), mtInternal);
+  assert(attach_points, "OOM");
+
+  // Fill attach points array.
+  char* attach_point = highest_start;
+  int i = 0;
+  while (i < num_attempts && attach_point >= lowest_start) {
+    attach_points[i] = attach_point;
+    i++;
+    // Handle overflow correctly!
+    if ((uintptr_t)attach_point > stepsize) {
+      attach_point -= stepsize;
+    } else {
+      attach_point = 0;
+    }
+  }
+
+  attach_points[i] = NULL;
+
+  char* addr = os::attempt_reserve_memory_at_multiple(size, attach_points);
+
+  os::free(attach_points);
+
+  return addr;
+}
+
 void os::split_reserved_memory(char *base, size_t size,
                                  size_t split, bool realloc) {
   pd_split_reserved_memory(base, size, split, realloc);
 }
 
< prev index next >