In case of hugepages munmap requires size aligned to page.

Signed-off-by: Maxim Uvarov <maxim.uva...@linaro.org>
---
 v5: - fix alloc_hp_size define (somehow arm gcc finds that it can be 
uninitialized;
     - remove goto and make if cases more readable;


 platform/linux-generic/odp_shared_memory.c | 73 +++++++++++++++++++-----------
 test/validation/odp_shm.c                  |  4 ++
 2 files changed, 50 insertions(+), 27 deletions(-)

diff --git a/platform/linux-generic/odp_shared_memory.c 
b/platform/linux-generic/odp_shared_memory.c
index 23a9ceb..4689c5d 100644
--- a/platform/linux-generic/odp_shared_memory.c
+++ b/platform/linux-generic/odp_shared_memory.c
@@ -179,27 +179,32 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t 
size, uint64_t align,
        int map_flag = MAP_SHARED;
        /* If already exists: O_EXCL: error, O_TRUNC: truncate to zero */
        int oflag = O_RDWR | O_CREAT | O_TRUNC;
-       uint64_t alloc_size = size + align;
+       uint64_t alloc_size;
        uint64_t page_sz, huge_sz;
+       int ret;
+#ifdef MAP_HUGETLB
+       int need_huge_page = 0;
+       uint64_t alloc_hp_size;
+#endif
 
-       huge_sz = odp_sys_huge_page_size();
        page_sz = odp_sys_page_size();
+       alloc_size = size + align;
+
+#ifdef MAP_HUGETLB
+       huge_sz = odp_sys_huge_page_size();
+       need_huge_page =  (huge_sz && alloc_size > page_sz);
+       /* munmap for huge pages requires sizes round up by page */
+       alloc_hp_size = (size + align + (huge_sz - 1)) & (-huge_sz);
+#endif
 
        if (flags & ODP_SHM_PROC) {
                /* Creates a file to /dev/shm */
                fd = shm_open(name, oflag,
                              S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
-
                if (fd == -1) {
                        ODP_DBG("odp_shm_reserve: shm_open failed\n");
                        return ODP_SHM_INVALID;
                }
-
-               if (ftruncate(fd, alloc_size) == -1) {
-                       ODP_DBG("odp_shm_reserve: ftruncate failed\n");
-                       return ODP_SHM_INVALID;
-               }
-
        } else {
                map_flag |= MAP_ANONYMOUS;
        }
@@ -230,32 +235,47 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t 
size, uint64_t align,
        block = &odp_shm_tbl->block[i];
 
        block->hdl  = to_handle(i);
-       block->huge = 0;
        addr        = MAP_FAILED;
 
 #ifdef MAP_HUGETLB
        /* Try first huge pages */
-       if (huge_sz && alloc_size > page_sz) {
-               addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
-                           map_flag | MAP_HUGETLB, fd, 0);
+       if (need_huge_page) {
+               ret = 0;
+               if (flags & ODP_SHM_PROC)
+                       ret = ftruncate(fd, alloc_hp_size);
+
+               if (ret == 0) {
+                       addr = mmap(NULL, alloc_hp_size, PROT_READ | PROT_WRITE,
+                                       map_flag | MAP_HUGETLB, fd, 0);
+                       if (addr == MAP_FAILED) {
+                               ODP_DBG("odp_shm_reserve: mmap HP failed\n");
+                       } else {
+                               block->alloc_size = alloc_hp_size;
+                               block->huge = 1;
+                               block->page_sz = huge_sz;
+                       }
+               }
        }
 #endif
 
        /* Use normal pages for small or failed huge page allocations */
        if (addr == MAP_FAILED) {
-               addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
-                           map_flag, fd, 0);
-               block->page_sz = page_sz;
-       } else {
-               block->huge    = 1;
-               block->page_sz = huge_sz;
-       }
-
-       if (addr == MAP_FAILED) {
-               /* Alloc failed */
-               odp_spinlock_unlock(&odp_shm_tbl->lock);
-               ODP_DBG("odp_shm_reserve: mmap failed\n");
-               return ODP_SHM_INVALID;
+               ret = 0;
+               if (flags & ODP_SHM_PROC)
+                       ret = ftruncate(fd, alloc_size);
+               if (ret == 0) {
+                       addr = mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
+                                       map_flag, fd, 0);
+                       if (addr == MAP_FAILED) {
+                               odp_spinlock_unlock(&odp_shm_tbl->lock);
+                               ODP_DBG("odp_shm_reserve: mmap failed\n");
+                               return ODP_SHM_INVALID;
+                       } else {
+                               block->alloc_size = alloc_size;
+                               block->huge = 0;
+                               block->page_sz = page_sz;
+                       }
+               }
        }
 
        block->addr_orig = addr;
@@ -267,7 +287,6 @@ odp_shm_t odp_shm_reserve(const char *name, uint64_t size, 
uint64_t align,
        block->name[ODP_SHM_NAME_LEN - 1] = 0;
        block->size       = size;
        block->align      = align;
-       block->alloc_size = alloc_size;
        block->flags      = flags;
        block->fd         = fd;
        block->addr       = addr;
diff --git a/test/validation/odp_shm.c b/test/validation/odp_shm.c
index c26925b..4b1a38e 100644
--- a/test/validation/odp_shm.c
+++ b/test/validation/odp_shm.c
@@ -32,7 +32,11 @@ static void *run_shm_thread(void *arg)
        CU_ASSERT(0 == info.flags);
        CU_ASSERT(test_shared_data == info.addr);
        CU_ASSERT(sizeof(test_shared_data_t) <= info.size);
+#ifdef MAP_HUGETLB
+       CU_ASSERT(odp_sys_huge_page_size() == info.page_size);
+#else
        CU_ASSERT(odp_sys_page_size() == info.page_size);
+#endif
        odp_shm_print_all();
 
        fflush(stdout);
-- 
1.8.5.1.163.gd7aced9


_______________________________________________
lng-odp mailing list
lng-odp@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/lng-odp

Reply via email to