|
16 | 16 |
|
17 | 17 | #include "cachelib/shm/PosixShmSegment.h" |
18 | 18 |
|
| 19 | +#include <cstring> |
| 20 | + |
19 | 21 | #include <fcntl.h> |
20 | 22 | #include <folly/logging/xlog.h> |
21 | 23 | #include <sys/mman.h> |
22 | 24 | #include <sys/stat.h> |
23 | 25 | #include <sys/types.h> |
| 26 | +#include <numa.h> |
| 27 | +#include <numaif.h> |
24 | 28 |
|
25 | 29 | #include "cachelib/common/Utils.h" |
26 | 30 |
|
@@ -166,6 +170,29 @@ void munmapImpl(void* addr, size_t length) { |
166 | 170 | } |
167 | 171 | } |
168 | 172 |
|
| 173 | +void getMempolicyImpl(int &oldMode, NumaBitMask &memBindNumaNodes) { |
| 174 | + auto nodeMask = memBindNumaNodes.getNativeBitmask(); |
| 175 | + |
| 176 | + long ret = get_mempolicy(&oldMode, nodeMask->maskp, nodeMask->size, |
| 177 | + nullptr, 0); |
| 178 | + |
| 179 | + if (ret != 0) { |
| 180 | + util::throwSystemError(errno, folly::sformat("get_mempolicy() failed: {}", |
| 181 | + std::strerror(errno))); |
| 182 | + } |
| 183 | +} |
| 184 | + |
| 185 | +void setMempolicyImpl(int oldMode, const NumaBitMask &memBindNumaNodes) { |
| 186 | + auto nodeMask = memBindNumaNodes.getNativeBitmask(); |
| 187 | + |
| 188 | + long ret = set_mempolicy(oldMode, nodeMask->maskp, nodeMask->size); |
| 189 | + |
| 190 | + if (ret != 0) { |
| 191 | + util::throwSystemError(errno, folly::sformat("set_mempolicy() failed: {}", |
| 192 | + std::strerror(errno))); |
| 193 | + } |
| 194 | +} |
| 195 | + |
169 | 196 | } // namespace detail |
170 | 197 |
|
171 | 198 | PosixShmSegment::PosixShmSegment(ShmAttachT, |
@@ -312,13 +339,50 @@ void* PosixShmSegment::mapAddress(void* addr) const { |
312 | 339 | util::throwSystemError(EINVAL, "Address already mapped"); |
313 | 340 | } |
314 | 341 | XDCHECK(retAddr == addr || addr == nullptr); |
| 342 | + memBind(addr); |
315 | 343 | return retAddr; |
316 | 344 | } |
317 | 345 |
|
318 | 346 | void PosixShmSegment::unMap(void* addr) const { |
319 | 347 | detail::munmapImpl(addr, getSize()); |
320 | 348 | } |
321 | 349 |
|
| 350 | +static void forcePageAllocation(void* addr, size_t size, size_t pageSize) { |
| 351 | + char* startAddr = reinterpret_cast<char*>(addr); |
| 352 | + char* endAddr = startAddr + size; |
| 353 | + for (volatile char* curAddr = startAddr; curAddr < endAddr; curAddr += pageSize) { |
| 354 | + *curAddr = *curAddr; |
| 355 | + } |
| 356 | +} |
| 357 | + |
| 358 | +void PosixShmSegment::memBind(void* addr) const { |
| 359 | + if (opts_.memBindNumaNodes.empty()) { |
| 360 | + return; |
| 361 | + } |
| 362 | + |
| 363 | + NumaBitMask oldMemBindNumaNodes; |
| 364 | + int oldMode = 0; |
| 365 | + |
| 366 | + // mbind() cannot be used because mmap was called with MAP_SHARED flag |
| 367 | + // But we can set memory policy for current thread and force page allocation. |
| 368 | + // The following logic is used: |
| 369 | + // 1. Remember current memory policy for the current thread |
| 370 | + // 2. Set new memory policy as specified by config |
| 371 | + // 3. Force page allocation by touching every page in the segment |
| 372 | + // 4. Restore memory policy |
| 373 | + |
| 374 | + // Remember current memory policy |
| 375 | + detail::getMempolicyImpl(oldMode, oldMemBindNumaNodes); |
| 376 | + |
| 377 | + // Set memory bindings |
| 378 | + detail::setMempolicyImpl(MPOL_BIND, opts_.memBindNumaNodes); |
| 379 | + |
| 380 | + forcePageAllocation(addr, getSize(), detail::getPageSize(opts_.pageSize)); |
| 381 | + |
| 382 | + // Restore memory policy for the thread |
| 383 | + detail::setMempolicyImpl(oldMode, oldMemBindNumaNodes); |
| 384 | +} |
| 385 | + |
322 | 386 | std::string PosixShmSegment::createKeyForName( |
323 | 387 | const std::string& name) noexcept { |
324 | 388 | // ensure that the slash is always there in the head. repetitive |
|
0 commit comments