test/bpf: skip test if libpcap is unavailable
[dpdk.git] / app / test / test_malloc.c
index 67a48ba..de40e50 100644 (file)
@@ -2,13 +2,19 @@
  * Copyright(c) 2010-2019 Intel Corporation
  */
 
+#include "test.h"
+
 #include <stdio.h>
 #include <stdint.h>
 #include <string.h>
 #include <stdarg.h>
 #include <errno.h>
 #include <stdlib.h>
+#ifndef RTE_EXEC_ENV_WINDOWS
+#include <sys/mman.h>
+#endif
 #include <sys/queue.h>
+#include <unistd.h>
 
 #include <rte_common.h>
 #include <rte_memory.h>
 #include <rte_random.h>
 #include <rte_string_fns.h>
 
-#include "test.h"
-
 #define N 10000
 
-
 static int
 is_mem_on_socket(int32_t socket);
 
@@ -45,8 +48,8 @@ addr_to_socket(void *addr);
 static int
 is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2)
 {
-       unsigned long ptr1 = (unsigned long)p1;
-       unsigned long ptr2 = (unsigned long)p2;
+       uintptr_t ptr1 = (uintptr_t)p1;
+       uintptr_t ptr2 = (uintptr_t)p2;
 
        if (ptr2 >= ptr1 && (ptr2 - ptr1) < len1)
                return 1;
@@ -58,7 +61,7 @@ is_memory_overlap(void *p1, size_t len1, void *p2, size_t len2)
 static int
 is_aligned(void *p, int align)
 {
-       unsigned long addr = (unsigned long)p;
+       uintptr_t addr = (uintptr_t)p;
        unsigned mask = align - 1;
 
        if (addr & mask)
@@ -67,7 +70,7 @@ is_aligned(void *p, int align)
 }
 
 static int
-test_align_overlap_per_lcore(__attribute__((unused)) void *arg)
+test_align_overlap_per_lcore(__rte_unused void *arg)
 {
        const unsigned align1 = 8,
                        align2 = 64,
@@ -138,7 +141,7 @@ test_align_overlap_per_lcore(__attribute__((unused)) void *arg)
 }
 
 static int
-test_reordered_free_per_lcore(__attribute__((unused)) void *arg)
+test_reordered_free_per_lcore(__rte_unused void *arg)
 {
        const unsigned align1 = 8,
                        align2 = 64,
@@ -371,8 +374,16 @@ test_multi_alloc_statistics(void)
        return 0;
 }
 
+#ifdef RTE_EXEC_ENV_WINDOWS
 static int
 test_realloc(void)
+{
+       return TEST_SKIPPED;
+}
+#else
+
+static int
+test_realloc_socket(int socket)
 {
        const char hello_str[] = "Hello, world!";
        const unsigned size1 = 1024;
@@ -381,13 +392,15 @@ test_realloc(void)
        const unsigned size4 = size3 + 1024;
 
        /* test data is the same even if element is moved*/
-       char *ptr1 = rte_zmalloc(NULL, size1, RTE_CACHE_LINE_SIZE);
+       char *ptr1 = rte_zmalloc_socket(
+                       NULL, size1, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr1){
                printf("NULL pointer returned from rte_zmalloc\n");
                return -1;
        }
        strlcpy(ptr1, hello_str, size1);
-       char *ptr2 = rte_realloc(ptr1, size2, RTE_CACHE_LINE_SIZE);
+       char *ptr2 = rte_realloc_socket(
+                       ptr1, size2, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr2){
                rte_free(ptr1);
                printf("NULL pointer returned from rte_realloc\n");
@@ -411,7 +424,8 @@ test_realloc(void)
        /* now allocate third element, free the second
         * and resize third. It should not move. (ptr1 is now invalid)
         */
-       char *ptr3 = rte_zmalloc(NULL, size3, RTE_CACHE_LINE_SIZE);
+       char *ptr3 = rte_zmalloc_socket(
+                       NULL, size3, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr3){
                printf("NULL pointer returned from rte_zmalloc\n");
                rte_free(ptr2);
@@ -426,7 +440,8 @@ test_realloc(void)
                }
        rte_free(ptr2);
        /* first resize to half the size of the freed block */
-       char *ptr4 = rte_realloc(ptr3, size4, RTE_CACHE_LINE_SIZE);
+       char *ptr4 = rte_realloc_socket(
+                       ptr3, size4, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr4){
                printf("NULL pointer returned from rte_realloc\n");
                rte_free(ptr3);
@@ -438,7 +453,8 @@ test_realloc(void)
                return -1;
        }
        /* now resize again to the full size of the freed block */
-       ptr4 = rte_realloc(ptr3, size3 + size2 + size1, RTE_CACHE_LINE_SIZE);
+       ptr4 = rte_realloc_socket(ptr3, size3 + size2 + size1,
+                       RTE_CACHE_LINE_SIZE, socket);
        if (ptr3 != ptr4){
                printf("Unexpected - ptr4 != ptr3 on second resize\n");
                rte_free(ptr4);
@@ -449,12 +465,14 @@ test_realloc(void)
        /* now try a resize to a smaller size, see if it works */
        const unsigned size5 = 1024;
        const unsigned size6 = size5 / 2;
-       char *ptr5 = rte_malloc(NULL, size5, RTE_CACHE_LINE_SIZE);
+       char *ptr5 = rte_malloc_socket(
+                       NULL, size5, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr5){
                printf("NULL pointer returned from rte_malloc\n");
                return -1;
        }
-       char *ptr6 = rte_realloc(ptr5, size6, RTE_CACHE_LINE_SIZE);
+       char *ptr6 = rte_realloc_socket(
+                       ptr5, size6, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr6){
                printf("NULL pointer returned from rte_realloc\n");
                rte_free(ptr5);
@@ -471,7 +489,7 @@ test_realloc(void)
        const unsigned size7 = 1024;
        const unsigned orig_align = RTE_CACHE_LINE_SIZE;
        unsigned new_align = RTE_CACHE_LINE_SIZE * 2;
-       char *ptr7 = rte_malloc(NULL, size7, orig_align);
+       char *ptr7 = rte_malloc_socket(NULL, size7, orig_align, socket);
        if (!ptr7){
                printf("NULL pointer returned from rte_malloc\n");
                return -1;
@@ -479,7 +497,7 @@ test_realloc(void)
        /* calc an alignment we don't already have */
        while(RTE_PTR_ALIGN(ptr7, new_align) == ptr7)
                new_align *= 2;
-       char *ptr8 = rte_realloc(ptr7, size7, new_align);
+       char *ptr8 = rte_realloc_socket(ptr7, size7, new_align, socket);
        if (!ptr8){
                printf("NULL pointer returned from rte_realloc\n");
                rte_free(ptr7);
@@ -497,18 +515,21 @@ test_realloc(void)
         */
        unsigned size9 = 1024, size10 = 1024;
        unsigned size11 = size9 + size10 + 256;
-       char *ptr9 = rte_malloc(NULL, size9, RTE_CACHE_LINE_SIZE);
+       char *ptr9 = rte_malloc_socket(
+                       NULL, size9, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr9){
                printf("NULL pointer returned from rte_malloc\n");
                return -1;
        }
-       char *ptr10 = rte_malloc(NULL, size10, RTE_CACHE_LINE_SIZE);
+       char *ptr10 = rte_malloc_socket(
+                       NULL, size10, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr10){
                printf("NULL pointer returned from rte_malloc\n");
                return -1;
        }
        rte_free(ptr9);
-       char *ptr11 = rte_realloc(ptr10, size11, RTE_CACHE_LINE_SIZE);
+       char *ptr11 = rte_realloc_socket(
+                       ptr10, size11, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr11){
                printf("NULL pointer returned from rte_realloc\n");
                rte_free(ptr10);
@@ -525,7 +546,8 @@ test_realloc(void)
         * We should get a malloc of the size requested*/
        const size_t size12 = 1024;
        size_t size12_check;
-       char *ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE);
+       char *ptr12 = rte_realloc_socket(
+                       NULL, size12, RTE_CACHE_LINE_SIZE, socket);
        if (!ptr12){
                printf("NULL pointer returned from rte_realloc\n");
                return -1;
@@ -537,8 +559,28 @@ test_realloc(void)
        }
        rte_free(ptr12);
 
+       /* do the same, but for regular memory */
+       ptr12 = rte_realloc(NULL, size12, RTE_CACHE_LINE_SIZE);
+       if (!ptr12) {
+               printf("NULL pointer returned from rte_realloc\n");
+               return -1;
+       }
+       if (rte_malloc_validate(ptr12, &size12_check) < 0 ||
+                       size12_check != size12) {
+               rte_free(ptr12);
+               return -1;
+       }
+       rte_free(ptr12);
+
+       return 0;
+}
+
+static int
+test_realloc_numa(void)
+{
        /* check realloc_socket part */
        int32_t socket_count = 0, socket_allocated, socket;
+       void *ptr1, *ptr2;
        int ret = -1;
        size_t size = 1024;
 
@@ -570,19 +612,78 @@ test_realloc(void)
                }
        }
 
-       /* Print warnign if only a single socket, but don't fail the test */
+       /* Print warning if only a single socket, but don't fail the test */
        if (socket_count < 2)
                printf("WARNING: realloc_socket test needs memory on multiple sockets!\n");
 
        ret = 0;
 end:
        rte_free(ptr1);
+       return ret;
+}
+
+static int
+test_realloc(void)
+{
+       const char *heap_name = "realloc_heap";
+       int realloc_heap_socket;
+       unsigned int mem_sz = 1U << 13; /* 8K */
+       unsigned int page_sz = sysconf(_SC_PAGESIZE);
+       void *mem;
+       int ret;
+
+       /* page size may be bigger than total mem size, so adjust */
+       mem_sz = RTE_MAX(mem_sz, page_sz);
+
+       /*
+        * the realloc tests depend on specific layout of underlying memory, so
+        * to prevent accidental failures to do fragmented main heap, we will
+        * do all of our tests on an artificially created memory.
+        */
+       if (rte_malloc_heap_create(heap_name) != 0) {
+               printf("Failed to create external heap\n");
+               ret = -1;
+               goto end;
+       }
+       realloc_heap_socket = rte_malloc_heap_get_socket(heap_name);
+
+       mem = mmap(NULL, mem_sz, PROT_READ | PROT_WRITE,
+                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+       if (mem == MAP_FAILED) {
+               printf("Failed to allocate memory for external heap\n");
+               ret = -1;
+               goto heap_destroy;
+       }
+
+       if (rte_malloc_heap_memory_add(
+                       heap_name, mem, mem_sz, NULL, 0, page_sz) != 0) {
+               printf("Failed to add memory to external heap\n");
+               ret = -1;
+               goto mem_free;
+       }
+
+       /* run the socket-bound tests */
+       ret = test_realloc_socket(realloc_heap_socket);
+       if (ret != 0)
+               goto mem_remove;
 
+       /* now, run the NUMA node tests */
+       ret = test_realloc_numa();
+
+mem_remove:
+       rte_malloc_heap_memory_remove(heap_name, mem, mem_sz);
+mem_free:
+       munmap(mem, mem_sz);
+heap_destroy:
+       rte_malloc_heap_destroy(heap_name);
+end:
        return ret;
 }
 
+#endif /* !RTE_EXEC_ENV_WINDOWS */
+
 static int
-test_random_alloc_free(void *_ __attribute__((unused)))
+test_random_alloc_free(void *_ __rte_unused)
 {
        struct mem_list {
                struct mem_list *next;
@@ -722,7 +823,7 @@ test_zero_aligned_alloc(void)
 
 err_return:
        /*clean up */
-       if (p1) rte_free(p1);
+       rte_free(p1);
        return -1;
 }
 
@@ -738,6 +839,11 @@ test_malloc_bad_params(void)
        if (bad_ptr != NULL)
                goto err_return;
 
+       /* rte_realloc expected to return null with inappropriate size */
+       bad_ptr = rte_realloc(NULL, size, align);
+       if (bad_ptr != NULL)
+               goto err_return;
+
        /* rte_malloc expected to return null with inappropriate alignment */
        align = 17;
        size = 1024;
@@ -746,12 +852,31 @@ test_malloc_bad_params(void)
        if (bad_ptr != NULL)
                goto err_return;
 
+       /* rte_realloc expected to return null with inappropriate alignment */
+       bad_ptr = rte_realloc(NULL, size, align);
+       if (bad_ptr != NULL)
+               goto err_return;
+
+#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG)
+       /* this test can not be built, will get trapped at compile time! */
+#else
+       /* rte_malloc expected to return null with size will cause overflow */
+       align = RTE_CACHE_LINE_SIZE;
+       size = (size_t)-8;
+
+       bad_ptr = rte_malloc(type, size, align);
+       if (bad_ptr != NULL)
+               goto err_return;
+
+       bad_ptr = rte_realloc(NULL, size, align);
+       if (bad_ptr != NULL)
+               goto err_return;
+#endif
        return 0;
 
 err_return:
        /* clean up pointer */
-       if (bad_ptr)
-               rte_free(bad_ptr);
+       rte_free(bad_ptr);
        return -1;
 }
 
@@ -856,7 +981,7 @@ test_alloc_socket(void)
                }
        }
 
-       /* Print warnign if only a single socket, but don't fail the test */
+       /* Print warning if only a single socket, but don't fail the test */
        if (socket_count < 2) {
                printf("WARNING: alloc_socket test needs memory on multiple sockets!\n");
        }
@@ -895,11 +1020,11 @@ test_malloc(void)
        else printf("test_realloc() passed\n");
 
        /*----------------------------*/
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                rte_eal_remote_launch(test_align_overlap_per_lcore, NULL, lcore_id);
        }
 
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                if (rte_eal_wait_lcore(lcore_id) < 0)
                        ret = -1;
        }
@@ -910,11 +1035,11 @@ test_malloc(void)
        else printf("test_align_overlap_per_lcore() passed\n");
 
        /*----------------------------*/
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                rte_eal_remote_launch(test_reordered_free_per_lcore, NULL, lcore_id);
        }
 
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                if (rte_eal_wait_lcore(lcore_id) < 0)
                        ret = -1;
        }
@@ -925,11 +1050,11 @@ test_malloc(void)
        else printf("test_reordered_free_per_lcore() passed\n");
 
        /*----------------------------*/
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                rte_eal_remote_launch(test_random_alloc_free, NULL, lcore_id);
        }
 
-       RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+       RTE_LCORE_FOREACH_WORKER(lcore_id) {
                if (rte_eal_wait_lcore(lcore_id) < 0)
                        ret = -1;
        }