comparison src/share/vm/runtime/virtualspace.cpp @ 12110:4c84d351cca9

8007074: SIGSEGV at ParMarkBitMap::verify_clear() Summary: Replace the broken large pages implementation on Linux. New flag: -XX:+UseTransparentHugePages - Linux specific flag to turn on transparent huge page hinting with madvise(..., MAP_HUGETLB). Changed behavior: -XX:+UseLargePages - tries to use -XX:+UseTransparentHugePages before trying other large pages implementations (on Linux). Changed behavior: -XX:+UseHugeTLBFS - Use upfront allocation of Large Pages instead of using the broken implementation to dynamically committing large pages. Changed behavior: -XX:LargePageSizeInBytes - Turned off the ability to use this flag on Linux and provides warning to user if set to a value different than the OS chosen large page size. Changed behavior: Setting no large page size - Now defaults to use -XX:UseTransparentHugePages if the OS supports it. Previously, -XX:+UseHugeTLBFS was chosen if the OS was configured to use large pages. Reviewed-by: tschatzl, dcubed, brutisso
author stefank
date Fri, 16 Aug 2013 13:22:32 +0200
parents a837fa3d3f86
children c4c768305a8f e2722a66aba7
comparison
equal deleted inserted replaced
12108:badf4244ceae 12110:4c84d351cca9
40 # include "os_bsd.inline.hpp" 40 # include "os_bsd.inline.hpp"
41 #endif 41 #endif
42 42
43 43
44 // ReservedSpace 44 // ReservedSpace
45
46 // Dummy constructor
47 ReservedSpace::ReservedSpace() : _base(NULL), _size(0), _noaccess_prefix(0),
48 _alignment(0), _special(false), _executable(false) {
49 }
50
45 ReservedSpace::ReservedSpace(size_t size) { 51 ReservedSpace::ReservedSpace(size_t size) {
46 initialize(size, 0, false, NULL, 0, false); 52 size_t page_size = os::page_size_for_region(size, size, 1);
53 bool large_pages = page_size != (size_t)os::vm_page_size();
54 // Don't force the alignment to be large page aligned,
55 // since that will waste memory.
56 size_t alignment = os::vm_allocation_granularity();
57 initialize(size, alignment, large_pages, NULL, 0, false);
47 } 58 }
48 59
49 ReservedSpace::ReservedSpace(size_t size, size_t alignment, 60 ReservedSpace::ReservedSpace(size_t size, size_t alignment,
50 bool large, 61 bool large,
51 char* requested_address, 62 char* requested_address,
127 assert(requested_address != NULL, "huge noaccess prefix?"); 138 assert(requested_address != NULL, "huge noaccess prefix?");
128 } 139 }
129 140
130 if (special) { 141 if (special) {
131 142
132 base = os::reserve_memory_special(size, requested_address, executable); 143 base = os::reserve_memory_special(size, alignment, requested_address, executable);
133 144
134 if (base != NULL) { 145 if (base != NULL) {
135 if (failed_to_reserve_as_requested(base, requested_address, size, true)) { 146 if (failed_to_reserve_as_requested(base, requested_address, size, true)) {
136 // OS ignored requested address. Try different address. 147 // OS ignored requested address. Try different address.
137 return; 148 return;
138 } 149 }
139 // Check alignment constraints 150 // Check alignment constraints.
140 assert((uintptr_t) base % alignment == 0, 151 assert((uintptr_t) base % alignment == 0,
141 "Large pages returned a non-aligned address"); 152 err_msg("Large pages returned a non-aligned address, base: "
153 PTR_FORMAT " alignment: " PTR_FORMAT,
154 base, (void*)(uintptr_t)alignment));
142 _special = true; 155 _special = true;
143 } else { 156 } else {
144 // failed; try to reserve regular memory below 157 // failed; try to reserve regular memory below
145 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) || 158 if (UseLargePages && (!FLAG_IS_DEFAULT(UseLargePages) ||
146 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) { 159 !FLAG_IS_DEFAULT(LargePageSizeInBytes))) {
713 tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); 726 tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size());
714 tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); 727 tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high());
715 tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); 728 tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary());
716 } 729 }
717 730
731
732 /////////////// Unit tests ///////////////
733
734 #ifndef PRODUCT
735
736 #define test_log(...) \
737 do {\
738 if (VerboseInternalVMTests) { \
739 tty->print_cr(__VA_ARGS__); \
740 tty->flush(); \
741 }\
742 } while (false)
743
744 class TestReservedSpace : AllStatic {
745 public:
746 static void small_page_write(void* addr, size_t size) {
747 size_t page_size = os::vm_page_size();
748
749 char* end = (char*)addr + size;
750 for (char* p = (char*)addr; p < end; p += page_size) {
751 *p = 1;
752 }
753 }
754
755 static void release_memory_for_test(ReservedSpace rs) {
756 if (rs.special()) {
757 guarantee(os::release_memory_special(rs.base(), rs.size()), "Shouldn't fail");
758 } else {
759 guarantee(os::release_memory(rs.base(), rs.size()), "Shouldn't fail");
760 }
761 }
762
763 static void test_reserved_space1(size_t size, size_t alignment) {
764 test_log("test_reserved_space1(%p)", (void*) (uintptr_t) size);
765
766 assert(is_size_aligned(size, alignment), "Incorrect input parameters");
767
768 ReservedSpace rs(size, // size
769 alignment, // alignment
770 UseLargePages, // large
771 NULL, // requested_address
772 0); // noacces_prefix
773
774 test_log(" rs.special() == %d", rs.special());
775
776 assert(rs.base() != NULL, "Must be");
777 assert(rs.size() == size, "Must be");
778
779 assert(is_ptr_aligned(rs.base(), alignment), "aligned sizes should always give aligned addresses");
780 assert(is_size_aligned(rs.size(), alignment), "aligned sizes should always give aligned addresses");
781
782 if (rs.special()) {
783 small_page_write(rs.base(), size);
784 }
785
786 release_memory_for_test(rs);
787 }
788
789 static void test_reserved_space2(size_t size) {
790 test_log("test_reserved_space2(%p)", (void*)(uintptr_t)size);
791
792 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
793
794 ReservedSpace rs(size);
795
796 test_log(" rs.special() == %d", rs.special());
797
798 assert(rs.base() != NULL, "Must be");
799 assert(rs.size() == size, "Must be");
800
801 if (rs.special()) {
802 small_page_write(rs.base(), size);
803 }
804
805 release_memory_for_test(rs);
806 }
807
808 static void test_reserved_space3(size_t size, size_t alignment, bool maybe_large) {
809 test_log("test_reserved_space3(%p, %p, %d)",
810 (void*)(uintptr_t)size, (void*)(uintptr_t)alignment, maybe_large);
811
812 assert(is_size_aligned(size, os::vm_allocation_granularity()), "Must be at least AG aligned");
813 assert(is_size_aligned(size, alignment), "Must be at least aligned against alignment");
814
815 bool large = maybe_large && UseLargePages && size >= os::large_page_size();
816
817 ReservedSpace rs(size, alignment, large, false);
818
819 test_log(" rs.special() == %d", rs.special());
820
821 assert(rs.base() != NULL, "Must be");
822 assert(rs.size() == size, "Must be");
823
824 if (rs.special()) {
825 small_page_write(rs.base(), size);
826 }
827
828 release_memory_for_test(rs);
829 }
830
831
832 static void test_reserved_space1() {
833 size_t size = 2 * 1024 * 1024;
834 size_t ag = os::vm_allocation_granularity();
835
836 test_reserved_space1(size, ag);
837 test_reserved_space1(size * 2, ag);
838 test_reserved_space1(size * 10, ag);
839 }
840
841 static void test_reserved_space2() {
842 size_t size = 2 * 1024 * 1024;
843 size_t ag = os::vm_allocation_granularity();
844
845 test_reserved_space2(size * 1);
846 test_reserved_space2(size * 2);
847 test_reserved_space2(size * 10);
848 test_reserved_space2(ag);
849 test_reserved_space2(size - ag);
850 test_reserved_space2(size);
851 test_reserved_space2(size + ag);
852 test_reserved_space2(size * 2);
853 test_reserved_space2(size * 2 - ag);
854 test_reserved_space2(size * 2 + ag);
855 test_reserved_space2(size * 3);
856 test_reserved_space2(size * 3 - ag);
857 test_reserved_space2(size * 3 + ag);
858 test_reserved_space2(size * 10);
859 test_reserved_space2(size * 10 + size / 2);
860 }
861
862 static void test_reserved_space3() {
863 size_t ag = os::vm_allocation_granularity();
864
865 test_reserved_space3(ag, ag , false);
866 test_reserved_space3(ag * 2, ag , false);
867 test_reserved_space3(ag * 3, ag , false);
868 test_reserved_space3(ag * 2, ag * 2, false);
869 test_reserved_space3(ag * 4, ag * 2, false);
870 test_reserved_space3(ag * 8, ag * 2, false);
871 test_reserved_space3(ag * 4, ag * 4, false);
872 test_reserved_space3(ag * 8, ag * 4, false);
873 test_reserved_space3(ag * 16, ag * 4, false);
874
875 if (UseLargePages) {
876 size_t lp = os::large_page_size();
877
878 // Without large pages
879 test_reserved_space3(lp, ag * 4, false);
880 test_reserved_space3(lp * 2, ag * 4, false);
881 test_reserved_space3(lp * 4, ag * 4, false);
882 test_reserved_space3(lp, lp , false);
883 test_reserved_space3(lp * 2, lp , false);
884 test_reserved_space3(lp * 3, lp , false);
885 test_reserved_space3(lp * 2, lp * 2, false);
886 test_reserved_space3(lp * 4, lp * 2, false);
887 test_reserved_space3(lp * 8, lp * 2, false);
888
889 // With large pages
890 test_reserved_space3(lp, ag * 4 , true);
891 test_reserved_space3(lp * 2, ag * 4, true);
892 test_reserved_space3(lp * 4, ag * 4, true);
893 test_reserved_space3(lp, lp , true);
894 test_reserved_space3(lp * 2, lp , true);
895 test_reserved_space3(lp * 3, lp , true);
896 test_reserved_space3(lp * 2, lp * 2, true);
897 test_reserved_space3(lp * 4, lp * 2, true);
898 test_reserved_space3(lp * 8, lp * 2, true);
899 }
900 }
901
902 static void test_reserved_space() {
903 test_reserved_space1();
904 test_reserved_space2();
905 test_reserved_space3();
906 }
907 };
908
909 void TestReservedSpace_test() {
910 TestReservedSpace::test_reserved_space();
911 }
912
913 #endif // PRODUCT
914
718 #endif 915 #endif