diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -517,6 +517,7 @@ __kmpc_set_default_allocator __kmpc_get_default_allocator __kmpc_alloc + __kmpc_realloc __kmpc_free __kmpc_init_allocator __kmpc_destroy_allocator @@ -534,6 +535,7 @@ omp_get_supported_active_levels 758 omp_fulfill_event 759 omp_display_env 733 + 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 --- a/openmp/runtime/src/include/omp.h.var +++ b/openmp/runtime/src/include/omp.h.var @@ -323,9 +323,14 @@ extern omp_allocator_handle_t __KAI_KMPC_CONVENTION omp_get_default_allocator(void); # 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_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_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 --- a/openmp/runtime/src/kmp.h +++ b/openmp/runtime/src/kmp.h @@ -963,6 +963,9 @@ extern void __kmpc_set_default_allocator(int gtid, omp_allocator_handle_t al); 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_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 --- a/openmp/runtime/src/kmp_alloc.cpp +++ b/openmp/runtime/src/kmp_alloc.cpp @@ -1436,6 +1436,7 @@ 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; @@ -1460,6 +1461,7 @@ 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) { @@ -1575,6 +1577,48 @@ return desc.ptr_align; } +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); + KMP_DEBUG_ASSERT(size > 0); + + 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 --- a/openmp/runtime/src/kmp_csupport.cpp +++ b/openmp/runtime/src/kmp_csupport.cpp @@ -4207,6 +4207,12 @@ return __kmpc_alloc(__kmp_entry_gtid(), 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 --- a/openmp/runtime/src/kmp_stub.cpp +++ b/openmp/runtime/src/kmp_stub.cpp @@ -366,6 +366,12 @@ i; return malloc(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_realloc_def_fb.c b/openmp/runtime/test/api/omp_realloc_def_fb.c new file mode 100644 --- /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", a); + printf("allocator default created: %p\n", 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; + } +}