< 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 >