| 140 | } |
| 141 | |
| 142 | void SystemAllocator::Free(BufferPool::BufferHandle&& buffer) { |
| 143 | if (FLAGS_mmap_buffers) { |
| 144 | int rc = munmap(buffer.data(), buffer.len()); |
| 145 | DCHECK_EQ(rc, 0) << "Unexpected munmap() error: " << errno; |
| 146 | } else { |
| 147 | bool use_huge_pages = buffer.len() % HUGE_PAGE_SIZE == 0 && FLAGS_madvise_huge_pages; |
| 148 | if (use_huge_pages) { |
| 149 | // Undo the madvise so that is isn't a candidate to be newly backed by huge pages. |
| 150 | // We depend on TCMalloc's "aggressive decommit" mode decommitting the physical |
| 151 | // huge pages with madvise(DONTNEED) when we call free(). Otherwise, this huge |
| 152 | // page region may be divvied up and subsequently decommitted in smaller chunks, |
| 153 | // which may not actually release the physical memory, causing Impala physical |
| 154 | // memory usage to exceed the process limit. |
| 155 | #ifdef MADV_NOHUGEPAGE |
| 156 | // According to madvise() docs it may return EAGAIN to signal that we should retry. |
| 157 | int rc; |
| 158 | do { |
| 159 | rc = madvise(buffer.data(), buffer.len(), MADV_NOHUGEPAGE); |
| 160 | } while (rc == -1 && errno == EAGAIN); |
| 161 | DCHECK(rc == 0) << "madvise(MADV_NOHUGEPAGE) shouldn't fail" << errno; |
| 162 | #endif |
| 163 | } |
| 164 | free(buffer.data()); |
| 165 | } |
| 166 | buffer.Reset(); // Avoid DCHECK in ~BufferHandle(). |
| 167 | } |
| 168 | } |