|
Packit |
345191 |
/*
|
|
Packit |
345191 |
* Copyright (C) 2017 - 2020 Intel Corporation.
|
|
Packit |
345191 |
* All rights reserved.
|
|
Packit |
345191 |
*
|
|
Packit |
345191 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
345191 |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
345191 |
* 1. Redistributions of source code must retain the above copyright notice(s),
|
|
Packit |
345191 |
* this list of conditions and the following disclaimer.
|
|
Packit |
345191 |
* 2. Redistributions in binary form must reproduce the above copyright notice(s),
|
|
Packit |
345191 |
* this list of conditions and the following disclaimer in the documentation
|
|
Packit |
345191 |
* and/or other materials provided with the distribution.
|
|
Packit |
345191 |
*
|
|
Packit |
345191 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY EXPRESS
|
|
Packit |
345191 |
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
Packit |
345191 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
|
Packit |
345191 |
* EVENT SHALL THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
Packit |
345191 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
Packit |
345191 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
|
Packit |
345191 |
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
|
Packit |
345191 |
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
Packit |
345191 |
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
|
Packit |
345191 |
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
345191 |
*/
|
|
Packit |
345191 |
#include <memkind/internal/memkind_hbw.h>
|
|
Packit |
345191 |
|
|
Packit |
345191 |
#include "common.h"
|
|
Packit |
345191 |
#include "allocator_perf_tool/GTestAdapter.hpp"
|
|
Packit |
345191 |
#include "numa.h"
|
|
Packit |
345191 |
|
|
Packit |
345191 |
#include <memory>
|
|
Packit |
345191 |
|
|
Packit |
345191 |
namespace TestPolicy
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
typedef std::unique_ptr<struct bitmask, decltype(&numa_free_nodemask)>
|
|
Packit |
345191 |
unique_bitmask_ptr;
|
|
Packit |
345191 |
|
|
Packit |
345191 |
unique_bitmask_ptr make_nodemask_ptr()
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
return unique_bitmask_ptr(numa_allocate_nodemask(), numa_free_nodemask);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
unique_bitmask_ptr make_cpumask_ptr()
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
return unique_bitmask_ptr(numa_allocate_cpumask(), numa_free_nodemask);
|
|
Packit |
345191 |
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
int get_num_of_pages(const size_t size, const size_t page_size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
size_t pages_number = size / page_size;
|
|
Packit |
345191 |
pages_number += size % page_size ? 1 : 0;
|
|
Packit |
345191 |
return pages_number;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
std::vector<void *> get_address_of_pages(const void *ptr,
|
|
Packit |
345191 |
const size_t pages_number, const size_t page_size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
std::vector<void *> address(pages_number);
|
|
Packit |
345191 |
const size_t page_mask = ~(page_size-1);
|
|
Packit |
345191 |
address[0] = (void *)((uintptr_t)ptr &
|
|
Packit |
345191 |
page_mask); //aligned address of first page
|
|
Packit |
345191 |
for (size_t page_num = 1; page_num < pages_number; page_num++) {
|
|
Packit |
345191 |
address[page_num] = (char *)address[page_num-1] + page_size;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
return address;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
void record_page_association(const void *ptr, const size_t size,
|
|
Packit |
345191 |
const size_t page_size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
size_t pages_number = get_num_of_pages(size, page_size);
|
|
Packit |
345191 |
std::vector<void *> address = get_address_of_pages(ptr, pages_number,
|
|
Packit |
345191 |
page_size);
|
|
Packit |
345191 |
|
|
Packit |
345191 |
int max_node_id = numa_max_node();
|
|
Packit |
345191 |
std::vector<int> nodes(pages_number);
|
|
Packit |
345191 |
std::vector<int> pages_on_node(max_node_id+1);
|
|
Packit |
345191 |
|
|
Packit |
345191 |
if (move_pages(0, pages_number, address.data(), NULL, nodes.data(),
|
|
Packit |
345191 |
MPOL_MF_MOVE)) {
|
|
Packit |
345191 |
fprintf(stderr, "Error: move_pages() returned %s\n", strerror(errno));
|
|
Packit |
345191 |
return;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
for (size_t i = 0; i < pages_number; i++) {
|
|
Packit |
345191 |
if (nodes[i] < 0) {
|
|
Packit |
345191 |
fprintf(stderr,"Error: status of page %p is %d\n", address[i], nodes[i]);
|
|
Packit |
345191 |
return;
|
|
Packit |
345191 |
} else {
|
|
Packit |
345191 |
pages_on_node[nodes[i]]++;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
for (size_t i = 0; i < (size_t)max_node_id + 1; i++) {
|
|
Packit |
345191 |
if (pages_on_node[i] > 0) {
|
|
Packit |
345191 |
char buffer[1024];
|
|
Packit |
345191 |
snprintf(buffer, sizeof(buffer), "Node%zd", i);
|
|
Packit |
345191 |
GTestAdapter::RecordProperty(buffer, pages_on_node[i]);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
void check_numa_nodes(unique_bitmask_ptr &expected_bitmask, int policy,
|
|
Packit |
345191 |
void *ptr, size_t size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
|
|
Packit |
345191 |
const size_t page_size = sysconf(_SC_PAGESIZE);
|
|
Packit |
345191 |
size_t pages_number = get_num_of_pages(size, page_size);
|
|
Packit |
345191 |
std::vector<void *> address = get_address_of_pages(ptr, pages_number,
|
|
Packit |
345191 |
page_size);
|
|
Packit |
345191 |
unique_bitmask_ptr returned_bitmask = make_nodemask_ptr();
|
|
Packit |
345191 |
int status = -1;
|
|
Packit |
345191 |
|
|
Packit |
345191 |
for (size_t page_num = 0; page_num < address.size(); page_num++) {
|
|
Packit |
345191 |
ASSERT_EQ(0, get_mempolicy(&status, returned_bitmask->maskp,
|
|
Packit |
345191 |
returned_bitmask->size, address[page_num], MPOL_F_ADDR));
|
|
Packit |
345191 |
ASSERT_EQ(policy, status);
|
|
Packit |
345191 |
switch(policy) {
|
|
Packit |
345191 |
case MPOL_INTERLEAVE:
|
|
Packit |
345191 |
EXPECT_TRUE(numa_bitmask_equal(expected_bitmask.get(), returned_bitmask.get()));
|
|
Packit |
345191 |
break;
|
|
Packit |
345191 |
case MPOL_DEFAULT:
|
|
Packit |
345191 |
break;
|
|
Packit |
345191 |
case MPOL_BIND:
|
|
Packit |
345191 |
case MPOL_PREFERRED:
|
|
Packit |
345191 |
for(int i=0; i < numa_num_possible_nodes(); i++) {
|
|
Packit |
345191 |
if(numa_bitmask_isbitset(returned_bitmask.get(), i)) {
|
|
Packit |
345191 |
EXPECT_TRUE(numa_bitmask_isbitset(expected_bitmask.get(), i));
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
break;
|
|
Packit |
345191 |
default:
|
|
Packit |
345191 |
assert(!"Unknown policy\n");
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
void check_hbw_numa_nodes(int policy, void *ptr, size_t size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
unique_bitmask_ptr expected_bitmask = make_nodemask_ptr();
|
|
Packit |
345191 |
|
|
Packit |
345191 |
memkind_hbw_all_get_mbind_nodemask(NULL, expected_bitmask->maskp,
|
|
Packit |
345191 |
expected_bitmask->size);
|
|
Packit |
345191 |
check_numa_nodes(expected_bitmask, policy, ptr, size);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
void check_all_numa_nodes(int policy, void *ptr, size_t size)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
if (policy != MPOL_INTERLEAVE && policy != MPOL_DEFAULT) return;
|
|
Packit |
345191 |
|
|
Packit |
345191 |
unique_bitmask_ptr expected_bitmask = make_nodemask_ptr();
|
|
Packit |
345191 |
|
|
Packit |
345191 |
for(int i=0; i < numa_num_configured_nodes(); i++) {
|
|
Packit |
345191 |
numa_bitmask_setbit(expected_bitmask.get(), i);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
check_numa_nodes(expected_bitmask, policy, ptr, size);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
|
|
Packit |
345191 |
std::set<int> get_regular_numa_nodes(void)
|
|
Packit |
345191 |
{
|
|
Packit |
345191 |
struct bitmask *cpu_mask = numa_allocate_cpumask();
|
|
Packit |
345191 |
std::set<int> regular_nodes;
|
|
Packit |
345191 |
|
|
Packit |
345191 |
const int MAXNODE_ID = numa_max_node();
|
|
Packit |
345191 |
for (int id = 0; id <= MAXNODE_ID; ++id) {
|
|
Packit |
345191 |
numa_node_to_cpus(id, cpu_mask);
|
|
Packit |
345191 |
|
|
Packit |
345191 |
if (numa_bitmask_weight(cpu_mask) != 0) {
|
|
Packit |
345191 |
regular_nodes.insert(id);
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
numa_free_cpumask(cpu_mask);
|
|
Packit |
345191 |
|
|
Packit |
345191 |
return regular_nodes;
|
|
Packit |
345191 |
}
|
|
Packit |
345191 |
}
|