|
21 | 21 | #include <sys/mman.h> |
22 | 22 | #include <sys/stat.h> |
23 | 23 | #include <sys/types.h> |
| 24 | +#include <numa.h> |
| 25 | +#include <numaif.h> |
24 | 26 |
|
25 | 27 | #include "cachelib/common/Utils.h" |
26 | 28 |
|
@@ -176,13 +178,52 @@ void* PosixShmSegment::mapAddress(void* addr) const { |
176 | 178 | util::throwSystemError(EINVAL, "Address already mapped"); |
177 | 179 | } |
178 | 180 | XDCHECK(retAddr == addr || addr == nullptr); |
| 181 | + memBind(addr); |
179 | 182 | return retAddr; |
180 | 183 | } |
181 | 184 |
|
182 | 185 | void PosixShmSegment::unMap(void* addr) const { |
183 | 186 | detail::munmapImpl(addr, getSize()); |
184 | 187 | } |
185 | 188 |
|
| 189 | +static void forcePageAllocation(void* addr, size_t size, size_t pageSize) { |
| 190 | + for(volatile char* curAddr = (char*)addr; curAddr < (char*)addr+size; curAddr += pageSize) { |
| 191 | + *curAddr = *curAddr; |
| 192 | + } |
| 193 | +} |
| 194 | + |
| 195 | +void PosixShmSegment::memBind(void* addr) const { |
| 196 | + if(opts_.memBindNumaNodes.empty()) return; |
| 197 | + |
| 198 | + struct bitmask *oldNodeMask = numa_allocate_nodemask(); |
| 199 | + int oldMode = 0; |
| 200 | + struct bitmask *nodesMask = numa_allocate_nodemask(); |
| 201 | + auto guard = folly::makeGuard([&] { numa_bitmask_free(nodesMask); numa_bitmask_free(oldNodeMask); }); |
| 202 | + |
| 203 | + for(auto node : opts_.memBindNumaNodes) { |
| 204 | + numa_bitmask_setbit(nodesMask, node); |
| 205 | + } |
| 206 | + |
| 207 | + // mbind() cannot be used because mmap was called with MAP_SHARED flag |
| 208 | + // But we can set memory policy for current thread and force page allcoation. |
| 209 | + // The following logic is used: |
| 210 | + // 1. Remember current memory policy for the current thread |
| 211 | + // 2. Set new memory policy as specifiec by config |
| 212 | + // 3. Force page allocation by touching every page in the segment |
| 213 | + // 4. Restore memory policy |
| 214 | + |
| 215 | + // Remember current memory policy |
| 216 | + get_mempolicy(&oldMode, oldNodeMask->maskp, oldNodeMask->size, nullptr, 0); |
| 217 | + |
| 218 | + // Set memory bindings |
| 219 | + set_mempolicy(MPOL_BIND, nodesMask->maskp, nodesMask->size); |
| 220 | + |
| 221 | + forcePageAllocation(addr, getSize(), detail::getPageSize(opts_.pageSize)); |
| 222 | + |
| 223 | + // Restore memory policy for the thread |
| 224 | + set_mempolicy(oldMode, nodesMask->maskp, nodesMask->size); |
| 225 | +} |
| 226 | + |
186 | 227 | std::string PosixShmSegment::createKeyForName( |
187 | 228 | const std::string& name) noexcept { |
188 | 229 | // ensure that the slash is always there in the head. repetitive |
|
0 commit comments