From 5439db05e74044a239c0fd37f8594b6b67dd3c02 Mon Sep 17 00:00:00 2001 From: Nawrin Sultana Date: Fri, 6 Nov 2020 15:36:19 -0600 Subject: [PATCH] [OpenMP] Add omp_realloc implementation This patch adds omp_realloc function implementation according to OpenMP 5.1 specification. Differential Revision: https://reviews.llvm.org/D90971 --- openmp/runtime/src/dllexports | 2 ++ openmp/runtime/src/include/omp.h.var | 5 +++ openmp/runtime/src/kmp.h | 3 ++ openmp/runtime/src/kmp_alloc.cpp | 43 ++++++++++++++++++++++++ openmp/runtime/src/kmp_csupport.cpp | 6 ++++ openmp/runtime/src/kmp_stub.cpp | 6 ++++ openmp/runtime/test/api/omp_calloc_def_fb.c | 2 +- openmp/runtime/test/api/omp_calloc_size_0.c | 2 +- openmp/runtime/test/api/omp_realloc_def_fb.c | 40 ++++++++++++++++++++++ openmp/runtime/test/api/omp_realloc_null_ptr.c | 46 ++++++++++++++++++++++++++ openmp/runtime/test/api/omp_realloc_size_0.c | 46 ++++++++++++++++++++++++++ openmp/runtime/tools/generate-def.pl | 5 +-- 12 files changed, 202 insertions(+), 4 deletions(-) create mode 100644 openmp/runtime/test/api/omp_realloc_def_fb.c create mode 100644 openmp/runtime/test/api/omp_realloc_null_ptr.c create mode 100644 openmp/runtime/test/api/omp_realloc_size_0.c diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports index 5f7447d..da5a0c6 100644 --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -518,6 +518,7 @@ kmp_set_disp_num_buffers 890 __kmpc_get_default_allocator __kmpc_alloc __kmpc_calloc + __kmpc_realloc __kmpc_free __kmpc_init_allocator __kmpc_destroy_allocator @@ -536,6 +537,7 @@ kmp_set_disp_num_buffers 890 omp_fulfill_event 759 omp_display_env 733 omp_calloc 776 + omp_realloc 777 omp_null_allocator DATA omp_default_mem_alloc DATA diff --git a/openmp/runtime/src/include/omp.h.var b/openmp/runtime/src/include/omp.h.var index 440756d..510bfc2 100644 --- a/openmp/runtime/src/include/omp.h.var +++ b/openmp/runtime/src/include/omp.h.var @@ -324,10 +324,15 @@ # ifdef __cplusplus extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a = omp_null_allocator); extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, + omp_allocator_handle_t allocator = omp_null_allocator, + omp_allocator_handle_t free_allocator = omp_null_allocator); extern void __KAI_KMPC_CONVENTION omp_free(void * ptr, omp_allocator_handle_t a = omp_null_allocator); # else extern void *__KAI_KMPC_CONVENTION omp_alloc(size_t size, omp_allocator_handle_t a); extern void *__KAI_KMPC_CONVENTION omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a); + extern void *__KAI_KMPC_CONVENTION omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator); extern void __KAI_KMPC_CONVENTION omp_free(void *ptr, omp_allocator_handle_t a); # endif diff --git a/openmp/runtime/src/kmp.h b/openmp/runtime/src/kmp.h index 5f8e6c6..3acee73 100644 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -965,6 +965,9 @@ extern omp_allocator_handle_t __kmpc_get_default_allocator(int gtid); extern void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); extern void *__kmpc_calloc(int gtid, size_t nmemb, size_t sz, omp_allocator_handle_t al); +extern void *__kmpc_realloc(int gtid, void *ptr, size_t sz, + omp_allocator_handle_t al, + omp_allocator_handle_t free_al); extern void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t al); extern void __kmp_init_memkind(); diff --git a/openmp/runtime/src/kmp_alloc.cpp b/openmp/runtime/src/kmp_alloc.cpp index a727867..ad5ee4d 100644 --- a/openmp/runtime/src/kmp_alloc.cpp +++ b/openmp/runtime/src/kmp_alloc.cpp @@ -1436,6 +1436,7 @@ omp_allocator_handle_t __kmpc_get_default_allocator(int gtid) { typedef struct kmp_mem_desc { // Memory block descriptor void *ptr_alloc; // Pointer returned by allocator size_t size_a; // Size of allocated memory block (initial+descriptor+align) + size_t size_orig; // Original size requested void *ptr_align; // Pointer to aligned memory, returned kmp_allocator_t *allocator; // allocator } kmp_mem_desc_t; @@ -1464,6 +1465,7 @@ void *__kmpc_alloc(int gtid, size_t size, omp_allocator_handle_t allocator) { if (allocator > kmp_max_mem_alloc && al->alignment > 0) { align = al->alignment; // alignment requested by user } + desc.size_orig = size; desc.size_a = size + sz_desc + align; if (__kmp_memkind_available) { @@ -1612,6 +1614,47 @@ void *__kmpc_calloc(int gtid, size_t nmemb, size_t size, return ptr; } +void *__kmpc_realloc(int gtid, void *ptr, size_t size, + omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator) { + void *nptr = NULL; + KMP_DEBUG_ASSERT(__kmp_init_serial); + + if (size == 0) { + if (ptr != NULL) + __kmpc_free(gtid, ptr, free_allocator); + return nptr; + } + + KE_TRACE(25, ("__kmpc_realloc: T#%d (%p, %d, %p, %p)\n", gtid, ptr, (int)size, + allocator, free_allocator)); + + nptr = __kmpc_alloc(gtid, size, allocator); + + if (nptr != NULL && ptr != NULL) { + kmp_mem_desc_t desc; + kmp_uintptr_t addr_align; // address to return to caller + kmp_uintptr_t addr_descr; // address of memory block descriptor + + addr_align = (kmp_uintptr_t)ptr; + addr_descr = addr_align - sizeof(kmp_mem_desc_t); + desc = *((kmp_mem_desc_t *)addr_descr); // read descriptor + + KMP_DEBUG_ASSERT(desc.ptr_align == ptr); + KMP_DEBUG_ASSERT(desc.size_orig > 0); + KMP_DEBUG_ASSERT(desc.size_orig < desc.size_a); + KMP_MEMCPY((char *)nptr, (char *)ptr, + (size_t)((size < desc.size_orig) ? size : desc.size_orig)); + } + + if (nptr != NULL) { + __kmpc_free(gtid, ptr, free_allocator); + } + + KE_TRACE(25, ("__kmpc_realloc returns %p, T#%d\n", nptr, gtid)); + return nptr; +} + void __kmpc_free(int gtid, void *ptr, const omp_allocator_handle_t allocator) { KE_TRACE(25, ("__kmpc_free: T#%d free(%p,%p)\n", gtid, ptr, allocator)); if (ptr == NULL) diff --git a/openmp/runtime/src/kmp_csupport.cpp b/openmp/runtime/src/kmp_csupport.cpp index ead7855..119386c 100644 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -4213,6 +4213,12 @@ void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t allocator) { return __kmpc_calloc(__kmp_entry_gtid(), nmemb, size, allocator); } +void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator) { + return __kmpc_realloc(__kmp_entry_gtid(), ptr, size, allocator, + free_allocator); +} + void omp_free(void *ptr, omp_allocator_handle_t allocator) { __kmpc_free(__kmp_entry_gtid(), ptr, allocator); } diff --git a/openmp/runtime/src/kmp_stub.cpp b/openmp/runtime/src/kmp_stub.cpp index 058c7b4..ac96e4a 100644 --- a/openmp/runtime/src/kmp_stub.cpp +++ b/openmp/runtime/src/kmp_stub.cpp @@ -371,6 +371,12 @@ void *omp_calloc(size_t nmemb, size_t size, i; return calloc(nmemb, size); } +void *omp_realloc(void *ptr, size_t size, + const omp_allocator_handle_t allocator, + const omp_allocator_handle_t free_allocator) { + i; + return realloc(ptr, size); +} void omp_free(void *ptr, const omp_allocator_handle_t allocator) { i; free(ptr); diff --git a/openmp/runtime/test/api/omp_calloc_def_fb.c b/openmp/runtime/test/api/omp_calloc_def_fb.c index 9d74278..e9b90fb 100644 --- a/openmp/runtime/test/api/omp_calloc_def_fb.c +++ b/openmp/runtime/test/api/omp_calloc_def_fb.c @@ -12,7 +12,7 @@ int main() { at[1].key = omp_atk_fallback; at[1].value = omp_atv_default_mem_fb; a = omp_init_allocator(omp_large_cap_mem_space, 2, at); - printf("allocator large created: %p\n", a); + printf("allocator large created: %p\n", (void *)a); #pragma omp parallel num_threads(2) { int i = omp_get_thread_num(); diff --git a/openmp/runtime/test/api/omp_calloc_size_0.c b/openmp/runtime/test/api/omp_calloc_size_0.c index 6d329ce..0902ca6 100644 --- a/openmp/runtime/test/api/omp_calloc_size_0.c +++ b/openmp/runtime/test/api/omp_calloc_size_0.c @@ -13,7 +13,7 @@ int main() at[1].key = omp_atk_fallback; at[1].value = omp_atv_default_mem_fb; a = omp_init_allocator(omp_large_cap_mem_space, 2, at); - printf("allocator large created: %p\n", a); + printf("allocator large created: %p\n", (void *)a); #pragma omp parallel num_threads(2) { int i = omp_get_thread_num(); diff --git a/openmp/runtime/test/api/omp_realloc_def_fb.c b/openmp/runtime/test/api/omp_realloc_def_fb.c new file mode 100644 index 0000000..667172c --- /dev/null +++ b/openmp/runtime/test/api/omp_realloc_def_fb.c @@ -0,0 +1,40 @@ +// RUN: %libomp-compile-and-run + +#include +#include + +int main() { + omp_alloctrait_t at[2]; + omp_allocator_handle_t a; + omp_allocator_handle_t f_a; + void *ptr[2]; + void *nptr[2]; + at[0].key = omp_atk_pool_size; + at[0].value = 2 * 1024 * 1024; + at[1].key = omp_atk_fallback; + at[1].value = omp_atv_default_mem_fb; + + a = omp_init_allocator(omp_large_cap_mem_space, 2, at); + f_a = omp_init_allocator(omp_default_mem_space, 2, at); + printf("allocator large created: %p\n", (void *)a); + printf("allocator default created: %p\n", (void *)f_a); + + #pragma omp parallel num_threads(2) + { + int i = omp_get_thread_num(); + ptr[i] = omp_alloc(1024 * 1024, f_a); + #pragma omp barrier + nptr[i] = omp_realloc(ptr[i], 1024 * 1024, a, f_a); + #pragma omp barrier + printf("th %d, nptr %p\n", i, nptr[i]); + omp_free(nptr[i], a); + } + // Both pointers should be non-NULL + if (nptr[0] != NULL && nptr[1] != NULL) { + printf("passed\n"); + return 0; + } else { + printf("failed: pointers %p %p\n", nptr[0], nptr[1]); + return 1; + } +} diff --git a/openmp/runtime/test/api/omp_realloc_null_ptr.c b/openmp/runtime/test/api/omp_realloc_null_ptr.c new file mode 100644 index 0000000..1483e12 --- /dev/null +++ b/openmp/runtime/test/api/omp_realloc_null_ptr.c @@ -0,0 +1,46 @@ +// RUN: %libomp-compile-and-run + +#include +#include + +int main() +{ + omp_alloctrait_t at[2]; + omp_allocator_handle_t a; + omp_allocator_handle_t f_a; + void *ptr[2]; + void *nptr[2]; + at[0].key = omp_atk_pool_size; + at[0].value = 2*1024*1024; + at[1].key = omp_atk_fallback; + at[1].value = omp_atv_default_mem_fb; + + a = omp_init_allocator(omp_large_cap_mem_space, 2, at); + f_a = omp_init_allocator(omp_default_mem_space, 2, at); + printf("allocator large created: %p\n", (void *)a); + printf("allocator default created: %p\n", (void *)f_a); + + #pragma omp parallel num_threads(2) + { + int i = omp_get_thread_num(); + ptr[i] = omp_alloc(0, f_a); + #pragma omp barrier + nptr[i] = omp_realloc(ptr[i], 1024 * 1024, a, f_a); + #pragma omp barrier + printf("th %d, nptr %p\n", i, nptr[i]); + omp_free(nptr[i], a); + } + + // Both ptr pointers should be NULL + if (ptr[0] != NULL || ptr[1] != NULL) { + printf("failed: pointers %p %p\n", ptr[0], ptr[1]); + return 1; + } + // Both nptr pointers should be non-NULL + if (nptr[0] == NULL || nptr[1] == NULL) { + printf("failed: pointers %p %p\n", nptr[0], nptr[1]); + return 1; + } + printf("passed\n"); + return 0; +} diff --git a/openmp/runtime/test/api/omp_realloc_size_0.c b/openmp/runtime/test/api/omp_realloc_size_0.c new file mode 100644 index 0000000..bfd0275 --- /dev/null +++ b/openmp/runtime/test/api/omp_realloc_size_0.c @@ -0,0 +1,46 @@ +// RUN: %libomp-compile-and-run + +#include +#include + +int main() +{ + omp_alloctrait_t at[2]; + omp_allocator_handle_t a; + omp_allocator_handle_t f_a; + void *ptr[2]; + void *nptr[2]; + at[0].key = omp_atk_pool_size; + at[0].value = 2*1024*1024; + at[1].key = omp_atk_fallback; + at[1].value = omp_atv_default_mem_fb; + + a = omp_init_allocator(omp_large_cap_mem_space, 2, at); + f_a = omp_init_allocator(omp_default_mem_space, 2, at); + printf("allocator large created: %p\n", (void *)a); + printf("allocator default created: %p\n", (void *)f_a); + + #pragma omp parallel num_threads(2) + { + int i = omp_get_thread_num(); + ptr[i] = omp_alloc(1024 * 1024, f_a); + #pragma omp barrier + nptr[i] = omp_realloc(ptr[i], 0, a, f_a); + #pragma omp barrier + printf("th %d, nptr %p\n", i, nptr[i]); + omp_free(nptr[i], a); + } + + // Both ptr pointers should be non-NULL + if (ptr[0] == NULL || ptr[1] == NULL) { + printf("failed: pointers %p %p\n", ptr[0], ptr[1]); + return 1; + } + // Both nptr pointers should be NULL + if (nptr[0] != NULL || nptr[1] != NULL) { + printf("failed: pointers %p %p\n", nptr[0], nptr[1]); + return 1; + } + printf("passed\n"); + return 0; +} diff --git a/openmp/runtime/tools/generate-def.pl b/openmp/runtime/tools/generate-def.pl index b245387..771d5f0 100755 --- a/openmp/runtime/tools/generate-def.pl +++ b/openmp/runtime/tools/generate-def.pl @@ -108,8 +108,9 @@ sub process(\%) { foreach my $entry ( keys( %$entries ) ) { if ( not $entries->{ $entry }->{ obsolete } ) { my $ordinal = $entries->{ $entry }->{ ordinal }; - # omp_alloc, omp_calloc and omp_free are C/C++ only functions, skip "1000+ordinal" for them - if ( $entry =~ m{\A[ok]mp_} and $entry ne "omp_alloc" and $entry ne "omp_calloc" and $entry ne "omp_free" ) { + # omp_alloc, omp_calloc, omp_realloc and omp_free are C/C++ only functions, skip "1000+ordinal" for them + if ( $entry =~ m{\A[ok]mp_} and $entry ne "omp_alloc" and $entry ne "omp_calloc" and + $entry ne "omp_realloc" and $entry ne "omp_free" ) { if ( not defined( $ordinal ) ) { runtime_error( "Bad entry \"$entry\": ordinal number is not specified." -- 2.7.4