Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 29 */ | 29 */ |
| 30 | 30 |
| 31 #include "config.h" | 31 #include "config.h" |
| 32 #include "wtf/PartitionAlloc.h" | 32 #include "wtf/PartitionAlloc.h" |
| 33 | 33 |
| 34 #include "wtf/BitwiseOperations.h" | 34 #include "wtf/BitwiseOperations.h" |
| 35 #include "wtf/CPU.h" | |
| 35 #include "wtf/OwnPtr.h" | 36 #include "wtf/OwnPtr.h" |
| 36 #include "wtf/PassOwnPtr.h" | 37 #include "wtf/PassOwnPtr.h" |
| 37 #include <gtest/gtest.h> | 38 #include <gtest/gtest.h> |
| 38 #include <stdlib.h> | 39 #include <stdlib.h> |
| 39 #include <string.h> | 40 #include <string.h> |
| 40 | 41 |
| 41 #if OS(POSIX) | 42 #if OS(POSIX) |
| 42 #include <sys/mman.h> | 43 #include <sys/mman.h> |
| 44 #include <sys/resource.h> | |
| 45 #include <sys/time.h> | |
| 43 | 46 |
| 44 #ifndef MAP_ANONYMOUS | 47 #ifndef MAP_ANONYMOUS |
| 45 #define MAP_ANONYMOUS MAP_ANON | 48 #define MAP_ANONYMOUS MAP_ANON |
| 46 #endif | 49 #endif |
| 47 #endif // OS(POSIX) | 50 #endif // OS(POSIX) |
| 48 | 51 |
| 49 #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 52 #if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| 50 | 53 |
| 51 namespace { | 54 namespace { |
| 52 | 55 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 78 // bitrotted because no test calls it. | 81 // bitrotted because no test calls it. |
| 79 partitionDumpStats(*allocator.root()); | 82 partitionDumpStats(*allocator.root()); |
| 80 #endif | 83 #endif |
| 81 | 84 |
| 82 // We expect no leaks in the general case. We have a test for leak | 85 // We expect no leaks in the general case. We have a test for leak |
| 83 // detection. | 86 // detection. |
| 84 EXPECT_TRUE(allocator.shutdown()); | 87 EXPECT_TRUE(allocator.shutdown()); |
| 85 EXPECT_TRUE(genericAllocator.shutdown()); | 88 EXPECT_TRUE(genericAllocator.shutdown()); |
| 86 } | 89 } |
| 87 | 90 |
| 91 static bool SetAddressSpaceLimit() | |
| 92 { | |
| 93 #if !CPU(64BIT) | |
| 94 // 32 bits => address space is limited already. | |
| 95 return true; | |
| 96 #elif OS(POSIX) | |
| 97 const size_t kAddressSpaceLimit = static_cast<size_t>(4096) * 1024 * 1024; | |
| 98 struct rlimit limit; | |
| 99 if (getrlimit(RLIMIT_AS, &limit) != 0) | |
| 100 return false; | |
| 101 if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > kAddressSpaceLimit) { | |
| 102 limit.rlim_cur = kAddressSpaceLimit; | |
| 103 if (setrlimit(RLIMIT_AS, &limit) != 0) | |
| 104 return false; | |
| 105 } | |
| 106 return true; | |
| 107 #else | |
| 108 return false; | |
|
Nico
2015/08/08 19:46:50
cevans: I found this pretty confusing – DoReturnNu
| |
| 109 #endif | |
| 110 } | |
| 111 | |
| 112 static bool ClearAddressSpaceLimit() | |
| 113 { | |
| 114 #if !CPU(64BIT) | |
| 115 return true; | |
| 116 #elif OS(POSIX) | |
| 117 struct rlimit limit; | |
| 118 if (getrlimit(RLIMIT_AS, &limit) != 0) | |
| 119 return false; | |
| 120 limit.rlim_cur = limit.rlim_max; | |
| 121 if (setrlimit(RLIMIT_AS, &limit) != 0) | |
| 122 return false; | |
| 123 return true; | |
| 124 #else | |
| 125 return false; | |
| 126 #endif | |
| 127 } | |
| 128 | |
| 88 static WTF::PartitionPage* GetFullPage(size_t size) | 129 static WTF::PartitionPage* GetFullPage(size_t size) |
| 89 { | 130 { |
| 90 size_t realSize = size + kExtraAllocSize; | 131 size_t realSize = size + kExtraAllocSize; |
| 91 size_t bucketIdx = realSize >> WTF::kBucketShift; | 132 size_t bucketIdx = realSize >> WTF::kBucketShift; |
| 92 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; | 133 WTF::PartitionBucket* bucket = &allocator.root()->buckets()[bucketIdx]; |
| 93 size_t numSlots = (bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / realSize; | 134 size_t numSlots = (bucket->numSystemPagesPerSlotSpan * WTF::kSystemPageSize) / realSize; |
| 94 void* first = 0; | 135 void* first = 0; |
| 95 void* last = 0; | 136 void* last = 0; |
| 96 size_t i; | 137 size_t i; |
| 97 for (i = 0; i < numSlots; ++i) { | 138 for (i = 0; i < numSlots; ++i) { |
| (...skipping 992 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1090 ptr = partitionAllocGeneric(genericAllocator.root(), size); | 1131 ptr = partitionAllocGeneric(genericAllocator.root(), size); |
| 1091 EXPECT_TRUE(ptr); | 1132 EXPECT_TRUE(ptr); |
| 1092 partitionFreeGeneric(genericAllocator.root(), ptr); | 1133 partitionFreeGeneric(genericAllocator.root(), ptr); |
| 1093 | 1134 |
| 1094 EXPECT_TRUE(bucket->activePagesHead); | 1135 EXPECT_TRUE(bucket->activePagesHead); |
| 1095 EXPECT_TRUE(bucket->freePagesHead); | 1136 EXPECT_TRUE(bucket->freePagesHead); |
| 1096 | 1137 |
| 1097 TestShutdown(); | 1138 TestShutdown(); |
| 1098 } | 1139 } |
| 1099 | 1140 |
| 1141 #if !CPU(64BIT) || OS(POSIX) | |
| 1142 | |
| 1143 // Tests that if an allocation fails in "return null" mode, repeating it doesn't | |
| 1144 // crash, and still returns null. The test tries to allocate 6 GB of memory in | |
| 1145 // 512 kB blocks. On 64-bit POSIX systems, the address space is limited to 4 GB | |
| 1146 // using setrlimit() first. | |
| 1147 TEST(PartitionAllocTest, RepeatedReturnNull) | |
| 1148 { | |
| 1149 TestSetup(); | |
| 1150 | |
| 1151 EXPECT_TRUE(SetAddressSpaceLimit()); | |
| 1152 | |
| 1153 // 512 kB x 12288 == 6 GB | |
| 1154 const size_t blockSize = 512 * 1024; | |
| 1155 const int numAllocations = 12288; | |
| 1156 | |
| 1157 void* ptrs[numAllocations]; | |
| 1158 int i; | |
| 1159 | |
| 1160 for (i = 0; i < numAllocations; ++i) { | |
| 1161 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), WTF::Parti tionAllocReturnNull, blockSize); | |
| 1162 if (!ptrs[i]) { | |
| 1163 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), WTF::P artitionAllocReturnNull, blockSize); | |
| 1164 EXPECT_FALSE(ptrs[i]); | |
| 1165 break; | |
| 1166 } | |
| 1167 } | |
| 1168 | |
| 1169 // We shouldn't succeed in allocating all 6 GB of memory. If we do, then | |
| 1170 // we're not actually testing anything here. | |
| 1171 EXPECT_LT(i, numAllocations); | |
| 1172 | |
| 1173 // Free, reallocate and free again each block we allocated. We do this to | |
| 1174 // check that freeing memory also works correctly after a failed allocation. | |
| 1175 for (--i; i >= 0; --i) { | |
| 1176 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); | |
| 1177 ptrs[i] = partitionAllocGenericFlags(genericAllocator.root(), WTF::Parti tionAllocReturnNull, blockSize); | |
| 1178 EXPECT_TRUE(ptrs[i]); | |
| 1179 partitionFreeGeneric(genericAllocator.root(), ptrs[i]); | |
| 1180 } | |
| 1181 | |
| 1182 EXPECT_TRUE(ClearAddressSpaceLimit()); | |
| 1183 | |
| 1184 TestShutdown(); | |
| 1185 } | |
| 1186 | |
| 1187 #endif // !CPU(64BIT) || OS(POSIX) | |
| 1188 | |
| 1100 #if !OS(ANDROID) | 1189 #if !OS(ANDROID) |
| 1101 | 1190 |
| 1102 // Make sure that malloc(-1) dies. | 1191 // Make sure that malloc(-1) dies. |
| 1103 // In the past, we had an integer overflow that would alias malloc(-1) to | 1192 // In the past, we had an integer overflow that would alias malloc(-1) to |
| 1104 // malloc(0), which is not good. | 1193 // malloc(0), which is not good. |
| 1105 TEST(PartitionAllocDeathTest, LargeAllocs) | 1194 TEST(PartitionAllocDeathTest, LargeAllocs) |
| 1106 { | 1195 { |
| 1107 TestSetup(); | 1196 TestSetup(); |
| 1108 // Largest alloc. | 1197 // Largest alloc. |
| 1109 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size _t>(-1)), ""); | 1198 EXPECT_DEATH(partitionAllocGeneric(genericAllocator.root(), static_cast<size _t>(-1)), ""); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1189 EXPECT_EQ(32u, WTF::countLeadingZerosSizet(0u)); | 1278 EXPECT_EQ(32u, WTF::countLeadingZerosSizet(0u)); |
| 1190 EXPECT_EQ(31u, WTF::countLeadingZerosSizet(1u)); | 1279 EXPECT_EQ(31u, WTF::countLeadingZerosSizet(1u)); |
| 1191 EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1u << 30)); | 1280 EXPECT_EQ(1u, WTF::countLeadingZerosSizet(1u << 30)); |
| 1192 EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1u << 31)); | 1281 EXPECT_EQ(0u, WTF::countLeadingZerosSizet(1u << 31)); |
| 1193 #endif | 1282 #endif |
| 1194 } | 1283 } |
| 1195 | 1284 |
| 1196 } // namespace | 1285 } // namespace |
| 1197 | 1286 |
| 1198 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) | 1287 #endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR) |
| OLD | NEW |