diff mbox

[PATCHv5] hugepages: align mmap size for hugepages

Message ID 1422274391-18907-1-git-send-email-maxim.uvarov@linaro.org
State New
Headers show

Commit Message

Maxim Uvarov Jan. 26, 2015, 12:13 p.m. UTC
In case of hugepages munmap requires size aligned to page.

Signed-off-by: Maxim Uvarov <maxim.uvarov@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(-)

Comments

Maxim Uvarov Jan. 26, 2015, 12:30 p.m. UTC | #1
skip this patch. Did not account one more comment about ftuncate error.

Maxim.

On 01/26/2015 03:13 PM, Maxim Uvarov wrote:
> In case of hugepages munmap requires size aligned to page.
>
> Signed-off-by: Maxim Uvarov <maxim.uvarov@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);
diff mbox

Patch

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);