Commit 7de51eb9 authored by Nicolas Denoyelle's avatar Nicolas Denoyelle Committed by Swann Perarnau

[test] add area test for linux

parent 4c6b4490
......@@ -51,6 +51,12 @@ stamp-h1
/missing
/stamp-h1
version.h
/m4/libtool.m4
/m4/ltmain.sh
/m4/ltoptions.m4
/m4/ltsugar.m4
/m4/ltversion.m4
/m4/lt~obsolete.m4
# autotest
tests/**/*.trs
......@@ -65,3 +71,6 @@ tests/**/*.log
# editors
*~
# package config
aml.pc
......@@ -15,63 +15,89 @@
#include <numa.h>
#include <numaif.h>
/* Bind memory on given nodeset with MPOL_BIND policy */
/* allowed binding flags */
#define AML_AREA_LINUX_BINDING_FLAG_BIND (MPOL_BIND)
#define AML_AREA_LINUX_BINDING_FLAG_INTERLEAVE (MPOL_INTERLEAVE)
#define AML_AREA_LINUX_BINDING_FLAG_PREFERRED (MPOL_PREFERRED)
/* Flags ti pass */
#define AML_AREA_LINUX_MMAP_FLAG_PRIVATE (MAP_PRIVATE)
#define AML_AREA_LINUX_MMAP_FLAG_SHARED (MAP_SHARED)
/* allowed mmap flags to pass */
#define AML_AREA_LINUX_MMAP_FLAG_PRIVATE (MAP_PRIVATE | MAP_ANONYMOUS)
#define AML_AREA_LINUX_MMAP_FLAG_SHARED (MAP_SHARED | MAP_ANONYMOUS)
/* User data stored inside area */
/** User data stored inside area **/
struct aml_area_linux_data {
struct bitmask *nodeset; /* numanodes to use */
int binding_flags; /* numaif.h mbind policy or AML_AREA_LINUX_FLAG_*/
int mmap_flags; /* mmap flags */
/** numanodes to use **/
struct bitmask *nodeset;
/** numaif.h mbind policy or AML_AREA_LINUX_FLAG_* **/
int binding_flags;
/** mmap flags **/
int mmap_flags;
};
/** Initialize area data with struct aml_area_linux_binding **/
/**
* Initialize area data with struct aml_area_linux_binding. Subsequent calls to
* aml_area_mmap() with this returned area will apply binding settings.
* Returns NULL on failure with aml_errno set to:
* - AML_AREA_ENOMEM if there is not enough memory available for the operation
* - AML_AREA_EINVAL flags were not one of linux area flags.
* - AML_AREA_EDOM if binding nodeset is out of allowed nodeset.
**/
struct aml_area* aml_area_linux_create(const int mmap_flags,
const struct aml_bitmap *nodemask,
const int binding_flags);
/** Destroy area data containing struct aml_area_linux_binding **/
/**
* Destroy area data containing struct aml_area_linux_binding
**/
void
aml_area_linux_destroy(struct aml_area* area);
/** Bind memory to area data. Done in aml_area_linux_mmap() **/
/**
* Bind memory of size "size" pointed by "ptr" to binding set in "bind".
* If mbind call was not successfull, i.e AML_FAILURE is returned, then errno
* should be inspected for further error checking.
**/
int
aml_area_linux_mbind(struct aml_area_linux_data *bind,
void *ptr,
size_t size);
/** Function to check whether binding of a ptr area match area settings. **/
/**
* Function to check whether binding of a ptr obtained with
* aml_area_linux_mmap() then aml_area_linux_mbind() match area settings.
* Returns 1 if mapped memory binding in ptr match area_data binding settings,
* else 0.
**/
int
aml_area_linux_check_binding(struct aml_area_linux_data *area_data,
void *ptr,
size_t size);
/** Function call to aml_area_linux_mmap_generic() then bind the data. **/
/**
* mmap hook for aml area.
* Fails with AML_FAILURE. On failure errno should be checked for further
* error investigations.
**/
void*
aml_area_linux_mmap(const struct aml_area_data *area_data,
void *ptr,
size_t size);
/** Building block function for unmapping memory **/
/**
* munmap hook for aml area, to unmap memory mapped with aml_area_linux_mmap().
* Fails with AML_FAILURE. On failure errno should be checked for further
* error investigations.
**/
int
aml_area_linux_munmap(const struct aml_area_data* area_data,
aml_area_linux_munmap(const struct aml_area_data *area_data,
void *ptr,
const size_t size);
/* linux area hooks */
/** linux area hooks. mmap hook will also bind data unlike header mmap hook. **/
extern struct aml_area_ops aml_area_linux_ops;
/* Default linux area with private mapping and no binding. */
/** Default linux area with private mapping and no binding. **/
extern const struct aml_area aml_area_linux;
#endif //AML_AREA_LINUX_NUMA_H
......@@ -20,22 +20,29 @@ const char* aml_strerror(const int errno);
**/
void aml_perror(const char * msg);
#define AML_SUCCESS 0 /* Generic value for success */
#define AML_FAILURE -1 /* Generic value for failure */
/* Generic value for success */
#define AML_SUCCESS 0
/* Generic value for failure */
#define AML_FAILURE -1
/************************************
* Area error codes -2 .. -32
************************************/
#define AML_AREA_EINVAL -2 /* Invalid argument provided */
#define AML_AREA_ENOTSUP -3 /* Function not implemented for this type of area */
#define AML_AREA_ENOMEM -4 /* Allocation failed */
#define AML_AREA_EDOM -5 /* One arguent is out of allowed bounds */
/* Invalid argument provided */
#define AML_AREA_EINVAL -2
/* Function not implemented for this type of area */
#define AML_AREA_ENOTSUP -3
/* Allocation failed */
#define AML_AREA_ENOMEM -4
/* One arguent is out of allowed bounds */
#define AML_AREA_EDOM -5
/************************************
* error bound
************************************/
#define AML_ERROR_MAX -6 /* Last error */
/* Last error */
#define AML_ERROR_MAX -7
#endif
......@@ -16,6 +16,34 @@
#define AML_AREA_LINUX_MBIND_FLAGS MPOL_MF_MOVE
static int aml_area_linux_check_mmap_flags(const int mmap_flags){
switch(mmap_flags){
case AML_AREA_LINUX_MMAP_FLAG_PRIVATE:
break;
case AML_AREA_LINUX_MMAP_FLAG_SHARED:
break;
default:
return 0;
}
return 1;
}
static int aml_area_linux_check_binding_flags(const int binding_flags){
switch(binding_flags){
case AML_AREA_LINUX_BINDING_FLAG_BIND:
break;
case AML_AREA_LINUX_BINDING_FLAG_INTERLEAVE:
break;
case AML_AREA_LINUX_BINDING_FLAG_PREFERRED:
break;
default:
return 0;
}
return 1;
}
struct aml_area* aml_area_linux_create(const int mmap_flags,
const struct aml_bitmap *nodemask,
const int binding_flags)
......@@ -23,26 +51,47 @@ struct aml_area* aml_area_linux_create(const int mmap_flags,
struct aml_area_linux_data *d;
struct aml_area *area;
/* Check flags */
if(!aml_area_linux_check_mmap_flags(mmap_flags) ||
!aml_area_linux_check_binding_flags(binding_flags)){
aml_errno = AML_AREA_EINVAL;
return NULL;
}
d = malloc(sizeof(*d));
if(d == NULL){
aml_errno = AML_AREA_ENOMEM;
return NULL;
}
d->nodeset = numa_allocate_nodemask();
/* Check/set nodemask */
d->nodeset = numa_get_mems_allowed();
if(d->nodeset == NULL){
aml_errno = AML_AREA_ENOMEM;
goto err_with_data;
}
aml_bitmap_copy_to_ulong(nodemask, d->nodeset->maskp, d->nodeset->size);
if(nodemask != NULL){
int aml_last = aml_bitmap_last(nodemask);
int allowed_last = numa_bitmask_weight(d->nodeset);
while(!numa_bitmask_isbitset(d->nodeset, --allowed_last));
if(aml_last > allowed_last){
aml_errno = AML_AREA_EDOM;
goto err_with_nodeset;
}
aml_bitmap_copy_to_ulong(nodemask,
d->nodeset->maskp,
d->nodeset->size);
}
/* set area_data and area */
d->binding_flags = binding_flags;
d->mmap_flags = mmap_flags | MAP_ANONYMOUS;
d->mmap_flags = mmap_flags;
area = malloc(sizeof(*area));
if(area == NULL){
aml_errno = AML_AREA_ENOMEM;
goto err_with_data;
goto err_with_nodeset;
}
area->data = (struct aml_area_data*)d;
......@@ -50,6 +99,8 @@ struct aml_area* aml_area_linux_create(const int mmap_flags,
return area;
err_with_nodeset:
numa_free_nodemask(d->nodeset);
err_with_data:
free(d);
return NULL;
......@@ -88,19 +139,7 @@ aml_area_linux_mbind(struct aml_area_linux_data *bind,
if(err == 0)
return AML_SUCCESS;
switch(errno){
case EFAULT:
return AML_AREA_EDOM;
case EINVAL:
return AML_AREA_EINVAL;
case EIO:
return AML_AREA_EINVAL;
case ENOMEM:
return AML_AREA_ENOMEM;
case EPERM:
return AML_AREA_ENOTSUP;
}
return AML_FAILURE;
}
int
......@@ -130,12 +169,17 @@ aml_area_linux_check_binding(struct aml_area_linux_data *area_data,
if(mode != area_data->binding_flags)
err = 0;
for(i=0; i<numa_max_possible_node(); i++){
if(numa_bitmask_isbitset(nodeset, i) !=
numa_bitmask_isbitset(area_data->nodeset, i)){
err = 0;
break;
}
int ptr_set = numa_bitmask_isbitset(nodeset, i);
int bitmask_set = numa_bitmask_isbitset(area_data->nodeset, i);
if(mode == AML_AREA_LINUX_BINDING_FLAG_BIND && ptr_set != bitmask_set)
goto binding_failed;
if(mode == AML_AREA_LINUX_BINDING_FLAG_INTERLEAVE && ptr_set && !bitmask_set)
goto binding_failed;
}
goto out;
binding_failed:
err = 0;
out:
numa_free_nodemask(nodeset);
return err;
......@@ -155,36 +199,10 @@ void* aml_area_linux_mmap(const struct aml_area_data *area_data,
if(out == MAP_FAILED){
out = NULL;
switch(errno){
case EAGAIN:
aml_errno = AML_AREA_ENOMEM;
break;
case EINVAL:
aml_errno = AML_AREA_EINVAL;
break;
case ENOMEM:
aml_errno = AML_AREA_ENOMEM;
break;
default:
aml_errno = AML_AREA_EINVAL;
break;
}
}
if(out != NULL && (data->nodeset != NULL ||
data->binding_flags != MPOL_DEFAULT)){
int err = aml_area_linux_mbind(data, out, size);
if(err != AML_SUCCESS){
aml_errno = err;
goto binding_failed;
}
aml_errno = AML_FAILURE;
}
return out;
binding_failed:
munmap(out, size);
return NULL;
}
int
......@@ -194,10 +212,35 @@ aml_area_linux_munmap(__attribute__ ((unused)) const struct aml_area_data* area_
{
int err = munmap(ptr, size);
if(err == -1)
return AML_AREA_EINVAL;
return AML_FAILURE;
return AML_SUCCESS;
}
static void*
aml_area_linux_mmap_mbind(const struct aml_area_data *area_data,
void *ptr,
size_t size)
{
void * out = aml_area_linux_mmap(area_data, ptr, size);
if(out == NULL)
return NULL;
struct aml_area_linux_data *data = (struct aml_area_linux_data *) area_data;
if(data->nodeset != NULL || data->binding_flags != MPOL_DEFAULT){
int err = aml_area_linux_mbind(data, out, size);
if(err != AML_SUCCESS){
aml_errno = err;
munmap(out, size);
return NULL;
}
}
return out;
}
/*****************************************************************************
* Areas declaration
*****************************************************************************/
......@@ -205,11 +248,11 @@ aml_area_linux_munmap(__attribute__ ((unused)) const struct aml_area_data* area_
const struct aml_area_linux_data aml_area_linux_data_default = {
.nodeset = NULL,
.binding_flags = MPOL_DEFAULT,
.mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS
.mmap_flags = AML_AREA_LINUX_MMAP_FLAG_PRIVATE
};
struct aml_area_ops aml_area_linux_ops = {
.mmap = aml_area_linux_mmap,
.mmap = aml_area_linux_mmap_mbind,
.munmap = aml_area_linux_munmap
};
......
......@@ -2,12 +2,18 @@
#include "aml/utils/error.h"
static const char* aml_error_strings[-AML_ERROR_MAX] = {
[AML_SUCCESS] = "aml success! If this is unexpected, check that this is called right after aml function returning an error.",
[-AML_FAILURE] = "aml function call failed (generic error).",
[-AML_AREA_EINVAL] = "aml_area function called with invalid argument(s).",
[-AML_AREA_ENOTSUP] = "aml_area function is not implemented.",
[-AML_AREA_ENOMEM] = "Not enough memory to fulfill aml_area function call.",
[-AML_AREA_EDOM] = "An argument is out possible bounds for this function call.",
[AML_SUCCESS] =
"aml success! If this is unexpected, check that this is called right after aml function returning an error.",
[-AML_FAILURE] =
"aml function call failed (generic error).",
[-AML_AREA_EINVAL] =
"aml_area function called with invalid argument(s).",
[-AML_AREA_ENOTSUP] =
"aml_area function is not implemented.",
[-AML_AREA_ENOMEM] =
"Not enough memory to fulfill aml_area function call.",
[-AML_AREA_EDOM] =
"An argument is out possible bounds for this function call.",
};
const char*
......
......@@ -14,7 +14,8 @@ UTILS_TESTS = utils/test_vector \
utils/test_version
AREA_TESTS = \
area/test_area
area/test_area \
area/test_linux
TILING_TESTS = tiling/test_tiling \
tiling/test_tiling_2d
......@@ -29,7 +30,7 @@ SCRATCH_TESTS = scratch/test_scratch_seq \
UNIT_TESTS = $(UTILS_TESTS) \
$(TILING_TESTS) \
$(BINDING_TESTS) \
$(AREA_LINUX_TESTS) \
$(AREA_TESTS) \
$(DMA_LINUX_TESTS) \
$(SCRATCH_TESTS)
......
......@@ -10,11 +10,12 @@
#include "aml.h"
#include "aml/area/area.h"
#include "aml/area/linux.h"
#include <assert.h>
void test_map(struct aml_area *area){
assert(area != NULL)
assert(area->ops->map != NULL);
assert(area->ops->unmap != NULL);
void test_map(const struct aml_area *area){
assert(area != NULL);
assert(area->ops->mmap != NULL);
assert(area->ops->munmap != NULL);
void *ptr;
int err;
......@@ -35,7 +36,7 @@ void test_aml_area(struct aml_area *area){
int main(int argc, char** argv){
aml_init(&argc, &argv);
test_aml_area(aml_area_linux);
test_map(&aml_area_linux);
aml_finalize();
return 0;
}
......@@ -7,72 +7,78 @@
*
* SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/
#include "aml.h"
#include "aml/area/area.h"
#include "aml/area/linux.h"
#include <assert.h>
#include <string.h>
const size_t sizes[3] = {1, 1<<12, 1<<20};
const int binding_flags[3] = {
AML_AREA_LINUX_BINDING_FLAG_BIND,
AML_AREA_LINUX_BINDING_FLAG_INTERLEAVE,
AML_AREA_LINUX_BINDING_FLAG_PREFERRED
};
const int mmap_flags[2] = {
AML_AREA_LINUX_MMAP_FLAG_PRIVATE,
AML_AREA_LINUX_MMAP_FLAG_SHARED
};
void test_binding(struct aml_area *area){
void test_binding(struct aml_bitmap *bitmap){
void *ptr;
int err;
size_t s;
const size_t sizes[2] = {1, 1<<20};
int bf, mf, i, nnodes, binding_flag, mmap_flag;
struct aml_area *area;
for(bf=0; bf<sizeof(binding_flags)/sizeof(*binding_flags); bf++){
binding_flag = binding_flags[bf];
for(mf=0; mf<sizeof(mmap_flags)/sizeof(*mmap_flags); mf++){
mmap_flag = mmap_flags[mf];
for(s = 0; s<sizeof(sizes)/sizeof(*sizes); s++){
ptr = NULL;
err = area->ops->map(area, &ptr, sizes[s]);
if(err == AML_AREA_ENOMEM)
continue;
if(err == AML_AREA_EINVAL)
continue;
if(err == AML_SUCCESS){
area = aml_area_linux_create(mmap_flag, bitmap, binding_flag);
assert(area != NULL);
ptr = area->ops->mmap((struct aml_area_data*)area->data,
NULL,
sizes[s]);
assert(ptr != NULL);
memset(ptr, 0, sizes[s]);
if(area->ops->check_binding)
assert(area->ops->check_binding(area, ptr, sizes[s]) > 0);
assert(area->ops->unmap(area, ptr, sizes[s]) == AML_SUCCESS);
} else
assert(0);
assert(aml_area_linux_check_binding((struct aml_area_linux_data*)area->data, ptr, sizes[s]) > 0);
assert(area->ops->munmap((struct aml_area_data*)area->data, ptr, sizes[s]) == AML_SUCCESS);
}
}
}
}
void test_bind(struct aml_area *area){
if(area->ops->bind == NULL)
return;
}
int err;
size_t i,j;
unsigned long flags = 1;
void test_bind(){
struct bitmask *nodeset;
int i, num_nodes;
struct aml_bitmap bitmap;
err = area->ops->bind(area, NULL, 0);
if(err == AML_SUCCESS)
test_binding(area);
nodeset = numa_get_mems_allowed();
num_nodes = numa_bitmask_weight(nodeset);
for(i = 0; i < sizeof(flags)*8 + 1; i++){
for(j = 0; j<AML_BITMAP_MAX; j++){
aml_bitmap_zero(&bitmap);
aml_bitmap_set(&bitmap, j);
err = area->ops->bind(area, &bitmap, flags);
if(err == AML_SUCCESS)
test_binding(area);
aml_bitmap_fill(&bitmap);
if(aml_bitmap_last(&bitmap) > num_nodes){
assert(aml_area_linux_create(AML_AREA_LINUX_MMAP_FLAG_PRIVATE,
&bitmap,
AML_AREA_LINUX_BINDING_FLAG_PREFERRED) == NULL);
assert(aml_errno == AML_AREA_EDOM);
}
flags = flags << 1;
}
}
void test_create(struct aml_area *area){
if(area->ops->create == NULL)
return;
assert(area->ops->destroy != NULL);
struct aml_area new;
int err;
test_binding(NULL);
new.ops = area->ops;
new.data = NULL;
assert(area->ops->create(&new) == AML_SUCCESS);
area->ops->destroy(&new);
aml_bitmap_zero(&bitmap);
for(i = 0; i<num_nodes; i++){
aml_bitmap_set(&bitmap, i);
test_binding(&bitmap);
aml_bitmap_clear(&bitmap, i);
}
}
int main(int argc, char** argv){
test_bind();
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment