Many open source projects have moved to using SPDX identifiers to specify license information, reducing the amount of boilerplate code in every source file. This patch replaces the bulk of SPDK .c, .cpp and Makefiles with the BSD-3-Clause identifier. Almost all of these files share the exact same license text, and this patch only modifies the files that contain the most common license text. There can be slight variations because the third clause contains company names - most say "Intel Corporation", but there are instances for Nvidia, Samsung, Eideticom and even "the copyright holder". Used a bash script to automate replacement of the license text with SPDX identifier which is checked into scripts/spdx.sh. Signed-off-by: Jim Harris <james.r.harris@intel.com> Change-Id: Iaa88ab5e92ea471691dc298cfe41ebfb5d169780 Reviewed-on: https://review.spdk.io/gerrit/c/spdk/spdk/+/12904 Community-CI: Broadcom CI <spdk-ci.pdl@broadcom.com> Community-CI: Mellanox Build Bot Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Aleksey Marchuk <alexeymar@nvidia.com> Reviewed-by: Changpeng Liu <changpeng.liu@intel.com> Reviewed-by: Dong Yi <dongx.yi@intel.com> Reviewed-by: Konrad Sztyber <konrad.sztyber@intel.com> Reviewed-by: Paul Luse <paul.e.luse@intel.com> Reviewed-by: <qun.wan@intel.com>
190 lines
4.7 KiB
C
190 lines
4.7 KiB
C
/* SPDX-License-Identifier: BSD-3-Clause
|
|
* Copyright (c) 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;
|
|
}
|