Spdk/test/env/mem_callbacks/mem_callbacks.c
paul luse a6dbe3721e update Intel copyright notices
per Intel policy to include file commit date using git cmd
below.  The policy does not apply to non-Intel (C) notices.

git log --follow -C90% --format=%ad --date default <file> | tail -1

and then pull just the 4 digit year from the result.

Intel copyrights were not added to files where Intel either had
no contribution ot the contribution lacked substance (ie license
header updates, formatting changes, etc).  Contribution date used
"--follow -C95%" to get the most accurate date.

Note that several files in this patch didn't end the license/(c)
block with a blank comment line so these were added as the vast
majority of files do have this last blank line.  Simply there for
consistency.

Signed-off-by: paul luse <paul.e.luse@intel.com>
Change-Id: Id5b7ce4f658fe87132f14139ead58d6e285c04d4
Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/15192
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Jim Harris <james.r.harris@intel.com>
Reviewed-by: Ben Walker <benjamin.walker@intel.com>
Community-CI: Mellanox Build Bot
2022-11-10 08:28:53 +00:00

190 lines
4.7 KiB
C

/* SPDX-License-Identifier: BSD-3-Clause
* Copyright (C) 2018 Intel Corporation.
* All rights reserved.
*/
#include "spdk/stdinc.h"
#include "spdk/util.h"
#include "spdk/queue.h"
#include "spdk_cunit.h"
#include <rte_config.h>
#include <rte_version.h>
#include <rte_malloc.h>
#include <rte_eal_memconfig.h>
#include <rte_eal.h>
struct mem_allocation {
uintptr_t vaddr;
size_t len;
TAILQ_ENTRY(mem_allocation) link;
};
static TAILQ_HEAD(, mem_allocation) g_mem_allocations = TAILQ_HEAD_INITIALIZER(g_mem_allocations);
static void
memory_hotplug_cb(enum rte_mem_event event_type, const void *addr, size_t len, void *arg)
{
struct mem_allocation *allocation;
if (event_type == RTE_MEM_EVENT_ALLOC) {
allocation = calloc(1, sizeof(*allocation));
SPDK_CU_ASSERT_FATAL(allocation != NULL);
printf("register %p %ju\n", addr, len);
allocation->vaddr = (uintptr_t)addr;
allocation->len = len;
TAILQ_INSERT_TAIL(&g_mem_allocations, allocation, link);
} else if (event_type == RTE_MEM_EVENT_FREE) {
TAILQ_FOREACH(allocation, &g_mem_allocations, link) {
if (allocation->vaddr == (uintptr_t)addr && allocation->len == len) {
break;
}
}
printf("unregister %p %ju %s\n", addr, len, allocation == NULL ? "FAILED" : "PASSED");
SPDK_CU_ASSERT_FATAL(allocation != NULL);
TAILQ_REMOVE(&g_mem_allocations, allocation, link);
free(allocation);
}
}
static int
memory_iter_cb(const struct rte_memseg_list *msl,
const struct rte_memseg *ms, size_t len, void *arg)
{
struct mem_allocation *allocation;
allocation = calloc(1, sizeof(*allocation));
SPDK_CU_ASSERT_FATAL(allocation != NULL);
printf("register %p %ju\n", ms->addr, len);
allocation->vaddr = (uintptr_t)ms->addr;
allocation->len = len;
TAILQ_INSERT_TAIL(&g_mem_allocations, allocation, link);
return 0;
}
static void
verify_buffer(void *_buf, size_t len)
{
uintptr_t buf = (uintptr_t)_buf;
struct mem_allocation *allocation;
SPDK_CU_ASSERT_FATAL(_buf != NULL);
printf("buf %p len %ju ", _buf, len);
TAILQ_FOREACH(allocation, &g_mem_allocations, link) {
if (buf >= allocation->vaddr &&
buf + len <= allocation->vaddr + allocation->len) {
break;
}
}
printf("%s\n", allocation == NULL ? "FAILED" : "PASSED");
CU_ASSERT(allocation != NULL);
}
static void
test(void)
{
void *buf1, *buf2, *buf3, *buf4;
size_t len1, len2, len3, len4;
printf("\n");
rte_mem_event_callback_register("test", memory_hotplug_cb, NULL);
rte_memseg_contig_walk(memory_iter_cb, NULL);
/* First allocate a 3MB buffer. This will allocate a 4MB hugepage
* region, with the 3MB buffer allocated from the end of it.
*/
len1 = 3 * 1024 * 1024;
printf("malloc %ju\n", len1);
buf1 = rte_malloc(NULL, len1, 0);
verify_buffer(buf1, len1);
/* Now allocate a very small buffer. This will get allocated from
* the previous 4MB hugepage allocation, just before the 3MB buffer
* allocated just above.
*/
len2 = 64;
printf("malloc %ju\n", len2);
buf2 = rte_malloc(NULL, len2, 0);
verify_buffer(buf2, len2);
/* Allocate a 4MB buffer. This should trigger a new hugepage allocation
* just for this 4MB buffer.
*/
len3 = 4 * 1024 * 1024;
printf("malloc %ju\n", len3);
buf3 = rte_malloc(NULL, len3, 0);
verify_buffer(buf3, len3);
/* Free the three buffers. Specifically free buf1 first. buf2 was
* allocated from the same huge page allocation as buf1 - so we want
* to make sure that DPDK doesn't try to free part of the first huge
* page allocation - it needs to wait until buf2 is also freed so it
* can free all of it.
*/
printf("free %p %ju\n", buf1, len1);
rte_free(buf1);
printf("free %p %ju\n", buf2, len2);
rte_free(buf2);
printf("free %p %ju\n", buf3, len3);
rte_free(buf3);
/* Do a single 8MB hugepage allocation and then free it. This covers
* the more simple case.
*/
len4 = 8 * 1024 * 1024;
printf("malloc %ju\n", len4);
buf4 = rte_malloc(NULL, len4, 0);
verify_buffer(buf4, len4);
printf("free %p %ju\n", buf4, len4);
rte_free(buf4);
}
int
main(int argc, char **argv)
{
CU_pSuite suite = NULL;
unsigned int num_failures;
char *dpdk_arg[] = {
"mem_callbacks", "-c 0x1",
"--base-virtaddr=0x200000000000",
"--match-allocations",
};
int rc;
rc = rte_eal_init(SPDK_COUNTOF(dpdk_arg), dpdk_arg);
if (rc < 0) {
printf("Err: Unable to initialize DPDK\n");
return 1;
}
if (CU_initialize_registry() != CUE_SUCCESS) {
return CU_get_error();
}
suite = CU_add_suite("memory", NULL, NULL);
if (suite == NULL) {
CU_cleanup_registry();
return CU_get_error();
}
if (
CU_add_test(suite, "test", test) == NULL
) {
CU_cleanup_registry();
return CU_get_error();
}
CU_basic_set_mode(CU_BRM_VERBOSE);
CU_basic_run_tests();
num_failures = CU_get_number_of_failures();
CU_cleanup_registry();
return num_failures;
}