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