| 148 | } |
| 149 | |
| 150 | bool MallocAllocator::allocateContiguousImpl( |
| 151 | MachinePageCount numPages, |
| 152 | Allocation* collateral, |
| 153 | ContiguousAllocation& allocation, |
| 154 | MachinePageCount maxPages) { |
| 155 | if (maxPages == 0) { |
| 156 | maxPages = numPages; |
| 157 | } else { |
| 158 | BOLT_CHECK_LE(numPages, maxPages); |
| 159 | } |
| 160 | if (collateral != nullptr) { |
| 161 | freeNonContiguous(*collateral); |
| 162 | } |
| 163 | auto numContiguousCollateralPages = allocation.numPages(); |
| 164 | if (numContiguousCollateralPages > 0) { |
| 165 | useHugePages(allocation, false); |
| 166 | if (::munmap(allocation.data(), allocation.maxSize()) < 0) { |
| 167 | BOLT_MEM_LOG(ERROR) << "munmap got " << folly::errnoStr(errno) << "for " |
| 168 | << allocation.data() << ", " << allocation.size(); |
| 169 | } |
| 170 | numMapped_.fetch_sub(numContiguousCollateralPages); |
| 171 | numAllocated_.fetch_sub(numContiguousCollateralPages); |
| 172 | numExternalMapped_.fetch_sub(numContiguousCollateralPages); |
| 173 | decrementUsage(AllocationTraits::pageBytes(numContiguousCollateralPages)); |
| 174 | allocation.clear(); |
| 175 | } |
| 176 | if (numPages == 0) { |
| 177 | return true; |
| 178 | } |
| 179 | |
| 180 | const auto totalBytes = AllocationTraits::pageBytes(numPages); |
| 181 | if (testingHasInjectedFailure(InjectedFailure::kCap) || |
| 182 | !incrementUsage(totalBytes)) { |
| 183 | const auto errorMsg = fmt::format( |
| 184 | "Exceeded memory allocator limit when allocating {} new pages, the " |
| 185 | "memory allocator capacity is {}", |
| 186 | numPages, |
| 187 | succinctBytes(capacity_)); |
| 188 | setAllocatorFailureMessage(errorMsg); |
| 189 | BOLT_MEM_LOG_EVERY_MS(WARNING, 1000) << errorMsg; |
| 190 | return false; |
| 191 | } |
| 192 | numAllocated_.fetch_add(numPages); |
| 193 | numMapped_.fetch_add(numPages); |
| 194 | numExternalMapped_.fetch_add(numPages); |
| 195 | void* data = ::mmap( |
| 196 | nullptr, |
| 197 | AllocationTraits::pageBytes(maxPages), |
| 198 | PROT_READ | PROT_WRITE, |
| 199 | MAP_PRIVATE | MAP_ANONYMOUS, |
| 200 | -1, |
| 201 | 0); |
| 202 | // TODO: add handling of MAP_FAILED. |
| 203 | allocation.set( |
| 204 | data, |
| 205 | AllocationTraits::pageBytes(numPages), |
| 206 | AllocationTraits::pageBytes(maxPages)); |
| 207 | useHugePages(allocation, true); |