|
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 |
|
@@ -312,13 +314,54 @@ void* PosixShmSegment::mapAddress(void* addr) const {
|
312 | 314 | util::throwSystemError(EINVAL, "Address already mapped");
|
313 | 315 | }
|
314 | 316 | XDCHECK(retAddr == addr || addr == nullptr);
|
| 317 | + memBind(addr); |
315 | 318 | return retAddr;
|
316 | 319 | }
|
317 | 320 |
|
318 | 321 | void PosixShmSegment::unMap(void* addr) const {
|
319 | 322 | detail::munmapImpl(addr, getSize());
|
320 | 323 | }
|
321 | 324 |
|
| 325 | +static void forcePageAllocation(void* addr, size_t size, size_t pageSize) { |
| 326 | + char* startAddr = reinterpret_cast<char*>(addr); |
| 327 | + char* endAddr = startAddr + size; |
| 328 | + for(volatile char* curAddr = startAddr; curAddr < endAddr; curAddr += pageSize) { |
| 329 | + *curAddr = *curAddr; |
| 330 | + } |
| 331 | +} |
| 332 | + |
| 333 | +void PosixShmSegment::memBind(void* addr) const { |
| 334 | + if(opts_.memBindNumaNodes.empty()) return; |
| 335 | + |
| 336 | + struct bitmask *oldNodeMask = numa_allocate_nodemask(); |
| 337 | + int oldMode = 0; |
| 338 | + struct bitmask *nodesMask = numa_allocate_nodemask(); |
| 339 | + auto guard = folly::makeGuard([&] { numa_bitmask_free(nodesMask); numa_bitmask_free(oldNodeMask); }); |
| 340 | + |
| 341 | + for(auto node : opts_.memBindNumaNodes) { |
| 342 | + numa_bitmask_setbit(nodesMask, node); |
| 343 | + } |
| 344 | + |
| 345 | + // mbind() cannot be used because mmap was called with MAP_SHARED flag |
| 346 | + // But we can set memory policy for current thread and force page allcoation. |
| 347 | + // The following logic is used: |
| 348 | + // 1. Remember current memory policy for the current thread |
| 349 | + // 2. Set new memory policy as specifiec by config |
| 350 | + // 3. Force page allocation by touching every page in the segment |
| 351 | + // 4. Restore memory policy |
| 352 | + |
| 353 | + // Remember current memory policy |
| 354 | + get_mempolicy(&oldMode, oldNodeMask->maskp, oldNodeMask->size, nullptr, 0); |
| 355 | + |
| 356 | + // Set memory bindings |
| 357 | + set_mempolicy(MPOL_BIND, nodesMask->maskp, nodesMask->size); |
| 358 | + |
| 359 | + forcePageAllocation(addr, getSize(), detail::getPageSize(opts_.pageSize)); |
| 360 | + |
| 361 | + // Restore memory policy for the thread |
| 362 | + set_mempolicy(oldMode, nodesMask->maskp, nodesMask->size); |
| 363 | +} |
| 364 | + |
322 | 365 | std::string PosixShmSegment::createKeyForName(
|
323 | 366 | const std::string& name) noexcept {
|
324 | 367 | // ensure that the slash is always there in the head. repetitive
|
|
0 commit comments