src/hotspot/os/solaris/os_solaris.cpp
changeset 55325 24c59b1579d7
parent 55291 47ee6c00d27c
child 55556 19d0b382f086
equal deleted inserted replaced
55324:b42cadf7eb4a 55325:24c59b1579d7
  2551 
  2551 
  2552 // Reserve memory at an arbitrary address, only if that area is
  2552 // Reserve memory at an arbitrary address, only if that area is
  2553 // available (and not reserved for something else).
  2553 // available (and not reserved for something else).
  2554 
  2554 
  2555 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
  2555 char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
  2556   const int max_tries = 10;
       
  2557   char* base[max_tries];
       
  2558   size_t size[max_tries];
       
  2559 
       
  2560   // Solaris adds a gap between mmap'ed regions.  The size of the gap
       
  2561   // is dependent on the requested size and the MMU.  Our initial gap
       
  2562   // value here is just a guess and will be corrected later.
       
  2563   bool had_top_overlap = false;
       
  2564   bool have_adjusted_gap = false;
       
  2565   size_t gap = 0x400000;
       
  2566 
       
  2567   // Assert only that the size is a multiple of the page size, since
  2556   // Assert only that the size is a multiple of the page size, since
  2568   // that's all that mmap requires, and since that's all we really know
  2557   // that's all that mmap requires, and since that's all we really know
  2569   // about at this low abstraction level.  If we need higher alignment,
  2558   // about at this low abstraction level.  If we need higher alignment,
  2570   // we can either pass an alignment to this method or verify alignment
  2559   // we can either pass an alignment to this method or verify alignment
  2571   // in one of the methods further up the call chain.  See bug 5044738.
  2560   // in one of the methods further up the call chain.  See bug 5044738.
  2572   assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
  2561   assert(bytes % os::vm_page_size() == 0, "reserving unexpected size block");
  2573 
  2562 
  2574   // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
  2563   // Since snv_84, Solaris attempts to honor the address hint - see 5003415.
  2575   // Give it a try, if the kernel honors the hint we can return immediately.
       
  2576   char* addr = Solaris::anon_mmap(requested_addr, bytes, 0, false);
  2564   char* addr = Solaris::anon_mmap(requested_addr, bytes, 0, false);
  2577 
  2565 
  2578   volatile int err = errno;
  2566   volatile int err = errno;
  2579   if (addr == requested_addr) {
  2567   if (addr == requested_addr) {
  2580     return addr;
  2568     return addr;
  2581   } else if (addr != NULL) {
  2569   }
       
  2570 
       
  2571   if (addr != NULL) {
  2582     pd_unmap_memory(addr, bytes);
  2572     pd_unmap_memory(addr, bytes);
  2583   }
  2573   }
  2584 
  2574 
  2585   if (log_is_enabled(Warning, os)) {
  2575   return NULL;
  2586     char buf[256];
       
  2587     buf[0] = '\0';
       
  2588     if (addr == NULL) {
       
  2589       jio_snprintf(buf, sizeof(buf), ": %s", os::strerror(err));
       
  2590     }
       
  2591     log_info(os)("attempt_reserve_memory_at: couldn't reserve " SIZE_FORMAT " bytes at "
       
  2592             PTR_FORMAT ": reserve_memory_helper returned " PTR_FORMAT
       
  2593             "%s", bytes, requested_addr, addr, buf);
       
  2594   }
       
  2595 
       
  2596   // Address hint method didn't work.  Fall back to the old method.
       
  2597   // In theory, once SNV becomes our oldest supported platform, this
       
  2598   // code will no longer be needed.
       
  2599   //
       
  2600   // Repeatedly allocate blocks until the block is allocated at the
       
  2601   // right spot. Give up after max_tries.
       
  2602   int i;
       
  2603   for (i = 0; i < max_tries; ++i) {
       
  2604     base[i] = reserve_memory(bytes);
       
  2605 
       
  2606     if (base[i] != NULL) {
       
  2607       // Is this the block we wanted?
       
  2608       if (base[i] == requested_addr) {
       
  2609         size[i] = bytes;
       
  2610         break;
       
  2611       }
       
  2612 
       
  2613       // check that the gap value is right
       
  2614       if (had_top_overlap && !have_adjusted_gap) {
       
  2615         size_t actual_gap = base[i-1] - base[i] - bytes;
       
  2616         if (gap != actual_gap) {
       
  2617           // adjust the gap value and retry the last 2 allocations
       
  2618           assert(i > 0, "gap adjustment code problem");
       
  2619           have_adjusted_gap = true;  // adjust the gap only once, just in case
       
  2620           gap = actual_gap;
       
  2621           log_info(os)("attempt_reserve_memory_at: adjusted gap to 0x%lx", gap);
       
  2622           unmap_memory(base[i], bytes);
       
  2623           unmap_memory(base[i-1], size[i-1]);
       
  2624           i-=2;
       
  2625           continue;
       
  2626         }
       
  2627       }
       
  2628 
       
  2629       // Does this overlap the block we wanted? Give back the overlapped
       
  2630       // parts and try again.
       
  2631       //
       
  2632       // There is still a bug in this code: if top_overlap == bytes,
       
  2633       // the overlap is offset from requested region by the value of gap.
       
  2634       // In this case giving back the overlapped part will not work,
       
  2635       // because we'll give back the entire block at base[i] and
       
  2636       // therefore the subsequent allocation will not generate a new gap.
       
  2637       // This could be fixed with a new algorithm that used larger
       
  2638       // or variable size chunks to find the requested region -
       
  2639       // but such a change would introduce additional complications.
       
  2640       // It's rare enough that the planets align for this bug,
       
  2641       // so we'll just wait for a fix for 6204603/5003415 which
       
  2642       // will provide a mmap flag to allow us to avoid this business.
       
  2643 
       
  2644       size_t top_overlap = requested_addr + (bytes + gap) - base[i];
       
  2645       if (top_overlap >= 0 && top_overlap < bytes) {
       
  2646         had_top_overlap = true;
       
  2647         unmap_memory(base[i], top_overlap);
       
  2648         base[i] += top_overlap;
       
  2649         size[i] = bytes - top_overlap;
       
  2650       } else {
       
  2651         size_t bottom_overlap = base[i] + bytes - requested_addr;
       
  2652         if (bottom_overlap >= 0 && bottom_overlap < bytes) {
       
  2653           if (bottom_overlap == 0) {
       
  2654             log_info(os)("attempt_reserve_memory_at: possible alignment bug");
       
  2655           }
       
  2656           unmap_memory(requested_addr, bottom_overlap);
       
  2657           size[i] = bytes - bottom_overlap;
       
  2658         } else {
       
  2659           size[i] = bytes;
       
  2660         }
       
  2661       }
       
  2662     }
       
  2663   }
       
  2664 
       
  2665   // Give back the unused reserved pieces.
       
  2666 
       
  2667   for (int j = 0; j < i; ++j) {
       
  2668     if (base[j] != NULL) {
       
  2669       unmap_memory(base[j], size[j]);
       
  2670     }
       
  2671   }
       
  2672 
       
  2673   return (i < max_tries) ? requested_addr : NULL;
       
  2674 }
  2576 }
  2675 
  2577 
  2676 bool os::pd_release_memory(char* addr, size_t bytes) {
  2578 bool os::pd_release_memory(char* addr, size_t bytes) {
  2677   size_t size = bytes;
  2579   size_t size = bytes;
  2678   return munmap(addr, size) == 0;
  2580   return munmap(addr, size) == 0;