void check_hbw_numa_nodes(int policy, void *ptr, size_t size) { unique_bitmask_ptr expected_bitmask = make_nodemask_ptr(); memkind_hbw_all_get_mbind_nodemask(NULL, expected_bitmask->maskp, expected_bitmask->size); check_numa_nodes(expected_bitmask, policy, ptr, size); }
/* This test is run with overridden MEMKIND_HBW_NODES environment variable * and tries to perform allocation from DRAM using hbw_malloc() using * default HBW_POLICY_PREFERRED policy. */ int main() { struct bitmask *expected_nodemask = NULL; struct bitmask *returned_nodemask = NULL; void *ptr = NULL; int ret = 0; int status = 0; ptr = hbw_malloc(KB); if (ptr == NULL) { printf("Error: allocation failed\n"); goto exit; } expected_nodemask = numa_allocate_nodemask(); status = memkind_hbw_all_get_mbind_nodemask(NULL, expected_nodemask->maskp, expected_nodemask->size); if (status != MEMKIND_ERROR_ENVIRON) { printf("Error: wrong return value from memkind_hbw_all_get_mbind_nodemask()\n"); printf("Expected: %d\n", MEMKIND_ERROR_ENVIRON); printf("Actual: %d\n", status); goto exit; } returned_nodemask = numa_allocate_nodemask(); status = get_mempolicy(NULL, returned_nodemask->maskp, returned_nodemask->size, ptr, MPOL_F_ADDR); if (status) { printf("Error: get_mempolicy() returned %d\n", status); goto exit; } ret = numa_bitmask_equal(returned_nodemask, expected_nodemask); if (!ret) { printf("Error: Memkind hbw and allocated pointer nodemasks are not equal\n"); } exit: if (expected_nodemask) { numa_free_nodemask(expected_nodemask); } if (returned_nodemask) { numa_free_nodemask(returned_nodemask); } if (ptr) { hbw_free(ptr); } return ret; }
MEMKIND_EXPORT int hbw_verify_memory_region(void* addr, size_t size, int flags) { /* * if size is invalid, flags have unsupported bit set or if addr is NULL. */ if (addr == NULL || size == 0 || flags & ~HBW_TOUCH_PAGES) { return EINVAL; } /* * 4KB is the smallest pagesize. When pagesize is bigger, pages are verified more than once */ const size_t page_size = sysconf(_SC_PAGESIZE); const size_t page_mask = ~(page_size-1); /* * block size should be power of two to enable compiler optimizations */ const unsigned block_size = 64; char *end = addr + size; char *aligned_beg = (char*)((uintptr_t)addr & page_mask); nodemask_t nodemask; struct bitmask expected_nodemask = {NUMA_NUM_NODES, nodemask.n}; memkind_hbw_all_get_mbind_nodemask(NULL, expected_nodemask.maskp, expected_nodemask.size); while(aligned_beg < end) { int nodes[block_size]; void* pages[block_size]; int i = 0, page_count = 0; char *iter_end = aligned_beg + block_size*page_size; if (iter_end > end) { iter_end = end; } while (aligned_beg < iter_end) { if (flags & HBW_TOUCH_PAGES) { hbw_touch_page(aligned_beg); } pages[page_count++] = aligned_beg; aligned_beg += page_size; } if (move_pages(0, page_count, pages, NULL, nodes, MPOL_MF_MOVE)) { return EFAULT; } for (i = 0; i < page_count; i++) { /* * negative value of nodes[i] indicates that move_pages could not establish * page location, e.g. addr is not pointing to valid virtual mapping */ if(nodes[i] < 0) { return -1; } /* * if nodes[i] is not present in expected_nodemask then * physical memory backing page is not hbw */ if (!numa_bitmask_isbitset(&expected_nodemask, nodes[i])) { return -1; } } } return 0; }