# Experiment: Check NUMA node from a pointer
contributed by `JulianATA(Julian Fang)`
## Environment
```bash
$uname -a
Linux 4.15.0-62-generic x86_64 GNU/Linux
```
## numaif.h/move_pages
```c
#include <numaif.h>
long move_pages(int pid, unsigned long count, void **pages,
const int *nodes, int *status, int flags);
```
:::warning
Link with -lnuma.
:::
:::info
nodes is an array of integers that specify the desired location for each page. Each element in the array is a node number. `nodes can also be NULL`, in which case move_pages() does not move any pages `but instead will return the node where each page currently resides`, in the status array. Obtaining the status of each page may be necessary to determine pages that need to be moved.
:::
## Implementation
### numa get node
* The goal here is to return the resident node of pointer p by using `move_pages()`.
```c
int get_node(void* p){
int numa_node[1] = {-1};
void* page = (void*)((size_t)p & ~((size_t)getpagesize()-1));
int err = move_pages(getpid(), 1, &page , NULL, numa_node, 0);
if(err == -1){
printf("move page failed.\n");
return -1;
}
return numa_node[0];
}
```
### Experment(`set_mempolicy()`)
```c
#include <stdio.h>
#include <stdlib.h>
#include <numaif.h> //set_mempolicy
#include "numagetnode.h"
#define MAX_NODES 4
#define TESTING_TIME 50
int main(int argc, char** argv) {
// get size and node informations
size_t size = atoi(argv[1]);
int node = atoi(argv[2]);
// set memory policy by node
unsigned long mask = (1UL << node);
long err = set_mempolicy(MPOL_BIND, &mask, MAX_NODES);
if(err == -1){
printf("Set mem policy failed.\n");
return -1;
}
// Allocation test
for(int i = 0; i< TESTING_TIME; i++){
void* p = malloc(size);
if(p == NULL){
printf("Allocate failed\n");
return -1;
}
printf("allocate an object with size:%ld on node:%d\n", size, node);
//get resident node by pointer
printf("memory %p is on node:%d\n", p, get_node(p));
}
return 0;
}
```
* Test for 50 times(default)
* Use `set_mempolicy()` as an instance.
* Using `malloc()`
```bash
$./get_node 128 2
allocate an object with size:128 on node:2
memory 0x55e131263130 is on node:2
allocate an object with size:128 on node:2
memory 0x55e1312631c0 is on node:2
allocate an object with size:128 on node:2
memory 0x55e131263250 is on node:2
allocate an object with size:128 on node:2
memory 0x55e1312632e0 is on node:2
allocate an object with size:128 on node:2
memory 0x55e131263370 is on node:2
allocate an object with size:128 on node:2
memory 0x55e131263400 is on node:2
allocate an object with size:128 on node:2
memory 0x55e131263490 is on node:2
allocate an object with size:128 on node:2
.
.
.
```
---
```c
#include <stdio.h>
#include <stdlib.h>
#include <numaif.h> //set_mempolicy
#include <sys/mman.h> //mmap
#include <unistd.h>
#include <string.h>
#include "numagetnode.h"
#define MAX_NODES 4
#define TESTING_TIME 5
int main(int argc, char** argv) {
// get node informations
int size = atoi(argv[1]);
int node = atoi(argv[2]);
// set memory policy by node
unsigned long mask = (1UL << node);
long err = set_mempolicy(MPOL_BIND, &mask, MAX_NODES);
if(err == -1){
printf("Set mem policy failed.\n");
return -1;
}
// Allocation test
for(int i = 0; i< TESTING_TIME; i++){
char* p = (char*)mmap(0, size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
if(p == NULL){
printf("Allocate failed\n");
return -1;
}
printf("allocate an object with size:%d on node:%d\n", size, node);
//need to be read|write before testing
memset(p, '\0', sizeof(p));
//get resident node by pointer
printf("memory %p is on node:%d\n", p, get_node(p));
}
```
* Test for 5 times(default)
* Use `set_mempolicy()` as an instance.
* Using `mmap`
```bash
$./main 1024 0
allocate an object with size:1024 on node:0
memory 0x7f25445f0000 is on node:0
allocate an object with size:1024 on node:0
memory 0x7f25445ef000 is on node:0
allocate an object with size:1024 on node:0
memory 0x7f25445ee000 is on node:0
allocate an object with size:1024 on node:0
memory 0x7f25445ed000 is on node:0
allocate an object with size:1024 on node:0
memory 0x7f25445ec000 is on node:0
```
###### tags: `NUMA`