diff --git a/openmp/runtime/src/dllexports b/openmp/runtime/src/dllexports --- a/openmp/runtime/src/dllexports +++ b/openmp/runtime/src/dllexports @@ -525,6 +525,7 @@ __kmpc_set_default_allocator __kmpc_get_default_allocator __kmpc_alloc + __kmpc_aligned_alloc __kmpc_calloc __kmpc_realloc __kmpc_free @@ -550,6 +551,8 @@ omp_display_env 733 omp_calloc 776 omp_realloc 777 + omp_aligned_alloc 778 + omp_aligned_calloc 806 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 @@ -431,14 +431,23 @@ 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_calloc(size_t nmemb, size_t size, omp_allocator_handle_t a = omp_null_allocator); + extern void *__KAI_KMPC_CONVENTION omp_aligned_alloc(size_t align, 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_aligned_calloc(size_t align, 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_aligned_alloc(size_t align, 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_aligned_calloc(size_t align, 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); diff --git a/openmp/runtime/src/include/omp_lib.h.var b/openmp/runtime/src/include/omp_lib.h.var --- a/openmp/runtime/src/include/omp_lib.h.var +++ b/openmp/runtime/src/include/omp_lib.h.var @@ -745,6 +745,55 @@ integer(c_int), value :: device_num end function omp_target_is_accessible + function omp_alloc(size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_alloc + integer(c_size_t), value :: size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_alloc + + function omp_aligned_alloc(alignment, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_aligned_alloc + integer(c_size_t), value :: alignment, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_aligned_alloc + + function omp_calloc(nmemb, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_calloc + integer(c_size_t), value :: nmemb, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_calloc + + function omp_aligned_calloc(alignment, nmemb, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_aligned_calloc + integer(c_size_t), value :: alignment, nmemb, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_aligned_calloc + + function omp_realloc(ptr, size, allocator, free_allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_realloc + type(c_ptr), value :: ptr + integer(c_size_t), value :: size + integer(omp_allocator_handle_kind), value :: allocator + integer(omp_allocator_handle_kind), value :: free_allocator + end function omp_realloc + + subroutine omp_free(ptr, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr + type(c_ptr), value :: ptr + integer(omp_allocator_handle_kind), value :: allocator + end subroutine omp_free + ! *** ! *** kmp_* entry points ! *** diff --git a/openmp/runtime/src/include/omp_lib.f90.var b/openmp/runtime/src/include/omp_lib.f90.var --- a/openmp/runtime/src/include/omp_lib.f90.var +++ b/openmp/runtime/src/include/omp_lib.f90.var @@ -650,6 +650,55 @@ integer(c_int), value :: device_num end function omp_target_is_accessible + function omp_alloc(size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_alloc + integer(c_size_t), value :: size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_alloc + + function omp_aligned_alloc(alignment, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_aligned_alloc + integer(c_size_t), value :: alignment, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_aligned_alloc + + function omp_calloc(nmemb, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_calloc + integer(c_size_t), value :: nmemb, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_calloc + + function omp_aligned_calloc(alignment, nmemb, size, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_aligned_calloc + integer(c_size_t), value :: alignment, nmemb, size + integer(omp_allocator_handle_kind), value :: allocator + end function omp_aligned_calloc + + function omp_realloc(ptr, size, allocator, free_allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t + type(c_ptr) omp_realloc + type(c_ptr), value :: ptr + integer(c_size_t), value :: size + integer(omp_allocator_handle_kind), value :: allocator + integer(omp_allocator_handle_kind), value :: free_allocator + end function omp_realloc + + subroutine omp_free(ptr, allocator) bind(c) + use omp_lib_kinds + use, intrinsic :: iso_c_binding, only : c_ptr + type(c_ptr), value :: ptr + integer(omp_allocator_handle_kind), value :: allocator + end subroutine omp_free + ! *** ! *** kmp_* entry points ! *** 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 @@ -989,7 +989,7 @@ typedef struct kmp_allocator_t { omp_memspace_handle_t memspace; void **memkind; // pointer to memkind - int alignment; + size_t alignment; omp_alloctrait_value_t fb; kmp_allocator_t *fb_data; kmp_uint64 pool_size; @@ -1003,13 +1003,25 @@ extern void __kmpc_destroy_allocator(int gtid, omp_allocator_handle_t al); extern void __kmpc_set_default_allocator(int gtid, omp_allocator_handle_t al); extern omp_allocator_handle_t __kmpc_get_default_allocator(int gtid); +// external interfaces, may be used by compiler extern void *__kmpc_alloc(int gtid, size_t sz, omp_allocator_handle_t al); +extern void *__kmpc_aligned_alloc(int gtid, size_t align, 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); +// internal interfaces, contain real implementation +extern void *__kmp_alloc(int gtid, size_t align, size_t sz, + omp_allocator_handle_t al); +extern void *__kmp_calloc(int gtid, size_t align, size_t nmemb, size_t sz, + omp_allocator_handle_t al); +extern void *__kmp_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(); extern void __kmp_fini_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 @@ -1484,31 +1484,74 @@ void *ptr_align; // Pointer to aligned memory, returned kmp_allocator_t *allocator; // allocator } kmp_mem_desc_t; -static int alignment = sizeof(void *); // let's align to pointer size +static int alignment = sizeof(void *); // align to pointer size by default +// external interfaces are wrappers over internal implementation void *__kmpc_alloc(int gtid, size_t size, omp_allocator_handle_t allocator) { + KE_TRACE(25, ("__kmpc_alloc: T#%d (%d, %p)\n", gtid, (int)size, allocator)); + void *ptr = __kmp_alloc(gtid, 0, size, allocator); + KE_TRACE(25, ("__kmpc_alloc returns %p, T#%d\n", ptr, gtid)); + return ptr; +} + +void *__kmpc_aligned_alloc(int gtid, size_t algn, size_t size, + omp_allocator_handle_t allocator) { + KE_TRACE(25, ("__kmpc_aligned_alloc: T#%d (%d, %d, %p)\n", gtid, (int)algn, + (int)size, allocator)); + void *ptr = __kmp_alloc(gtid, algn, size, allocator); + KE_TRACE(25, ("__kmpc_aligned_alloc returns %p, T#%d\n", ptr, gtid)); + return ptr; +} + +void *__kmpc_calloc(int gtid, size_t nmemb, size_t size, + omp_allocator_handle_t allocator) { + KE_TRACE(25, ("__kmpc_calloc: T#%d (%d, %d, %p)\n", gtid, (int)nmemb, + (int)size, allocator)); + void *ptr = __kmp_calloc(gtid, 0, nmemb, size, allocator); + KE_TRACE(25, ("__kmpc_calloc returns %p, T#%d\n", ptr, gtid)); + return ptr; +} + +void *__kmpc_realloc(int gtid, void *ptr, size_t size, + omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator) { + KE_TRACE(25, ("__kmpc_realloc: T#%d (%p, %d, %p, %p)\n", gtid, ptr, (int)size, + allocator, free_allocator)); + void *nptr = __kmp_realloc(gtid, ptr, size, allocator, free_allocator); + KE_TRACE(25, ("__kmpc_realloc returns %p, T#%d\n", nptr, gtid)); + return nptr; +} + +void __kmpc_free(int gtid, void *ptr, omp_allocator_handle_t allocator) { + KE_TRACE(25, ("__kmpc_free: T#%d free(%p,%p)\n", gtid, ptr, allocator)); + ___kmpc_free(gtid, ptr, allocator); + KE_TRACE(10, ("__kmpc_free: T#%d freed %p (%p)\n", gtid, ptr, allocator)); + return; +} + +// internal implementation, called from inside the library +void *__kmp_alloc(int gtid, size_t algn, size_t size, + omp_allocator_handle_t allocator) { void *ptr = NULL; kmp_allocator_t *al; KMP_DEBUG_ASSERT(__kmp_init_serial); - if (size == 0) return NULL; - if (allocator == omp_null_allocator) allocator = __kmp_threads[gtid]->th.th_def_allocator; - KE_TRACE(25, ("__kmpc_alloc: T#%d (%d, %p)\n", gtid, (int)size, allocator)); - al = RCAST(kmp_allocator_t *, CCAST(omp_allocator_handle_t, allocator)); + al = RCAST(kmp_allocator_t *, allocator); int sz_desc = sizeof(kmp_mem_desc_t); kmp_mem_desc_t desc; kmp_uintptr_t addr; // address returned by allocator kmp_uintptr_t addr_align; // address to return to caller kmp_uintptr_t addr_descr; // address of memory block descriptor - int align = alignment; // default alignment - if (allocator > kmp_max_mem_alloc && al->alignment > 0) { - align = al->alignment; // alignment requested by user - } + size_t align = alignment; // default alignment + if (allocator > kmp_max_mem_alloc && al->alignment > align) + align = al->alignment; // alignment required by allocator trait + if (align < algn) + align = algn; // max of allocator trait, parameter and sizeof(void*) desc.size_orig = size; desc.size_a = size + sz_desc + align; @@ -1537,7 +1580,7 @@ } else if (al->fb == omp_atv_allocator_fb) { KMP_ASSERT(al != al->fb_data); al = al->fb_data; - return __kmpc_alloc(gtid, size, (omp_allocator_handle_t)al); + return __kmp_alloc(gtid, algn, size, (omp_allocator_handle_t)al); } // else ptr == NULL; } else { // pool has enough space @@ -1551,7 +1594,7 @@ } else if (al->fb == omp_atv_allocator_fb) { KMP_ASSERT(al != al->fb_data); al = al->fb_data; - return __kmpc_alloc(gtid, size, (omp_allocator_handle_t)al); + return __kmp_alloc(gtid, algn, size, (omp_allocator_handle_t)al); } } } @@ -1567,7 +1610,7 @@ } else if (al->fb == omp_atv_allocator_fb) { KMP_ASSERT(al != al->fb_data); al = al->fb_data; - return __kmpc_alloc(gtid, size, (omp_allocator_handle_t)al); + return __kmp_alloc(gtid, algn, size, (omp_allocator_handle_t)al); } } } @@ -1623,7 +1666,7 @@ } else if (al->fb == omp_atv_allocator_fb) { KMP_ASSERT(al != al->fb_data); al = al->fb_data; - return __kmpc_alloc(gtid, size, (omp_allocator_handle_t)al); + return __kmp_alloc(gtid, algn, size, (omp_allocator_handle_t)al); } // else ptr == NULL; } else { // pool has enough space @@ -1639,7 +1682,7 @@ KMP_ASSERT(0); // abort fallback requested } // no sense to look for another fallback because of same internal alloc } - KE_TRACE(10, ("__kmpc_alloc: T#%d %p=alloc(%d)\n", gtid, ptr, desc.size_a)); + KE_TRACE(10, ("__kmp_alloc: T#%d %p=alloc(%d)\n", gtid, ptr, desc.size_a)); if (ptr == NULL) return NULL; @@ -1653,12 +1696,11 @@ *((kmp_mem_desc_t *)addr_descr) = desc; // save descriptor contents KMP_MB(); - KE_TRACE(25, ("__kmpc_alloc returns %p, T#%d\n", desc.ptr_align, gtid)); return desc.ptr_align; } -void *__kmpc_calloc(int gtid, size_t nmemb, size_t size, - omp_allocator_handle_t allocator) { +void *__kmp_calloc(int gtid, size_t algn, size_t nmemb, size_t size, + omp_allocator_handle_t allocator) { void *ptr = NULL; kmp_allocator_t *al; KMP_DEBUG_ASSERT(__kmp_init_serial); @@ -1666,10 +1708,7 @@ if (allocator == omp_null_allocator) allocator = __kmp_threads[gtid]->th.th_def_allocator; - KE_TRACE(25, ("__kmpc_calloc: T#%d (%d, %d, %p)\n", gtid, (int)nmemb, - (int)size, allocator)); - - al = RCAST(kmp_allocator_t *, CCAST(omp_allocator_handle_t, allocator)); + al = RCAST(kmp_allocator_t *, allocator); if (nmemb == 0 || size == 0) return ptr; @@ -1681,31 +1720,27 @@ return ptr; } - ptr = __kmpc_alloc(gtid, nmemb * size, allocator); + ptr = __kmp_alloc(gtid, algn, nmemb * size, allocator); if (ptr) { memset(ptr, 0x00, nmemb * size); } - KE_TRACE(25, ("__kmpc_calloc returns %p, T#%d\n", ptr, gtid)); return ptr; } -void *__kmpc_realloc(int gtid, void *ptr, size_t size, - omp_allocator_handle_t allocator, - omp_allocator_handle_t free_allocator) { +void *__kmp_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); + ___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); + nptr = __kmp_alloc(gtid, 0, size, allocator); if (nptr != NULL && ptr != NULL) { kmp_mem_desc_t desc; @@ -1724,15 +1759,13 @@ } if (nptr != NULL) { - __kmpc_free(gtid, ptr, free_allocator); + ___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)); +void ___kmpc_free(int gtid, void *ptr, omp_allocator_handle_t allocator) { if (ptr == NULL) return; @@ -1792,8 +1825,6 @@ } __kmp_thread_free(__kmp_thread_from_gtid(gtid), desc.ptr_alloc); } - KE_TRACE(10, ("__kmpc_free: T#%d freed %p (%p)\n", gtid, desc.ptr_alloc, - allocator)); } /* If LEAK_MEMORY is defined, __kmp_free() will *not* free memory. It causes 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 @@ -4327,24 +4327,35 @@ KA_TRACE(20, ("__kmpc_doacross_fini() exit: T#%d\n", gtid)); } -/* omp_alloc/omp_calloc/omp_free only defined for C/C++, not for Fortran */ +/* OpenMP 5.1 Memory Management routines */ void *omp_alloc(size_t size, omp_allocator_handle_t allocator) { - return __kmpc_alloc(__kmp_entry_gtid(), size, allocator); + return __kmp_alloc(__kmp_entry_gtid(), 0, size, allocator); +} + +void *omp_aligned_alloc(size_t align, size_t size, + omp_allocator_handle_t allocator) { + return __kmp_alloc(__kmp_entry_gtid(), align, size, allocator); } void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t allocator) { - return __kmpc_calloc(__kmp_entry_gtid(), nmemb, size, allocator); + return __kmp_calloc(__kmp_entry_gtid(), 0, nmemb, size, allocator); +} + +void *omp_aligned_calloc(size_t align, size_t nmemb, size_t size, + omp_allocator_handle_t allocator) { + return __kmp_calloc(__kmp_entry_gtid(), align, 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, + return __kmp_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); + ___kmpc_free(__kmp_entry_gtid(), ptr, allocator); } +/* end of OpenMP 5.1 Memory Management routines */ int __kmpc_get_target_offload(void) { if (!__kmp_init_serial) { 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 @@ -376,25 +376,85 @@ omp_memspace_handle_t const llvm_omp_target_device_mem_space = (omp_memspace_handle_t const)102; #endif /* KMP_OS_WINDOWS */ -void *omp_alloc(size_t size, const omp_allocator_handle_t allocator) { + +void *omp_alloc(size_t size, omp_allocator_handle_t allocator) { + i; + void *res; +#if KMP_OS_WINDOWS + // Returns a pointer to the memory block, or NULL if failed. + // Sets errno to ENOMEM or EINVAL if memory allocation failed or parameter + // validation failed. + res = _aligned_malloc(size, 1); +#else + res = malloc(size); +#endif + return res; +} + +void *omp_aligned_alloc(size_t a, size_t size, omp_allocator_handle_t al) { i; - return malloc(size); + int err; + void *res; +#if KMP_OS_WINDOWS + res = _aligned_malloc(size, a); +#else + if (err = posix_memalign(&res, a, size)) { + errno = err; // can be EINVAL or ENOMEM + res = NULL; + } +#endif + return res; +} + +void *omp_calloc(size_t nmemb, size_t size, omp_allocator_handle_t al) { + i; + void *res; +#if KMP_OS_WINDOWS + res = _aligned_recalloc(NULL, nmemb, size, 1); +#else + res = calloc(nmemb, size); +#endif + return res; } -void *omp_calloc(size_t nmemb, size_t size, - const omp_allocator_handle_t allocator) { + +void *omp_aligned_calloc(size_t a, size_t nmemb, size_t size, + omp_allocator_handle_t al) { i; - return calloc(nmemb, size); + int err; + void *res; +#if KMP_OS_WINDOWS + res = _aligned_recalloc(NULL, nmemb, size, a); +#else + if (err = posix_memalign(&res, a, nmemb * size)) { + errno = err; // can be EINVAL or ENOMEM + res = NULL; + } + memset(res, 0x00, size); +#endif + return res; } -void *omp_realloc(void *ptr, size_t size, - const omp_allocator_handle_t allocator, - const omp_allocator_handle_t free_allocator) { + +void *omp_realloc(void *ptr, size_t size, omp_allocator_handle_t al, + omp_allocator_handle_t free_al) { i; - return realloc(ptr, size); + void *res; +#if KMP_OS_WINDOWS + res = _aligned_realloc(ptr, size, 1); +#else + res = realloc(ptr, size); +#endif + return res; } -void omp_free(void *ptr, const omp_allocator_handle_t allocator) { + +void omp_free(void *ptr, omp_allocator_handle_t allocator) { i; +#if KMP_OS_WINDOWS + _aligned_free(ptr); +#else free(ptr); +#endif } + /* OpenMP 5.0 Affinity Format */ void omp_set_affinity_format(char const *format) { i; } size_t omp_get_affinity_format(char *buffer, size_t size) { diff --git a/openmp/runtime/test/api/omp_aligned_alloc.c b/openmp/runtime/test/api/omp_aligned_alloc.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/api/omp_aligned_alloc.c @@ -0,0 +1,85 @@ +// RUN: %libomp-compile-and-run +// UNSUPPORTED: gnu + +#include +#include +#include +#define NTH 8 +#define AL0 64 +#define AL1 128 + +int main() +{ + int err = 0; + omp_alloctrait_t at[3]; + omp_allocator_handle_t a; + void *p[NTH]; + at[0].key = omp_atk_pool_size; + at[0].value = 16*1024*1024; + at[1].key = omp_atk_fallback; + at[1].value = omp_atv_null_fb; + a = omp_init_allocator(omp_large_cap_mem_space, 2, at); + printf("allocator large created: %p\n", (void *)a); + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_alloc(AL0, 1024 * 1024, a); // API's alignment only + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL0) { + #pragma omp atomic + err++; + printf("Error param: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL0); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + at[2].key = omp_atk_alignment; + at[2].value = AL1; + a = omp_init_allocator(omp_large_cap_mem_space, 3, at); + printf("allocator large aligned %d created: %p\n", AL1, (void *)a); + if (a != omp_null_allocator) + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_alloc(AL0, 1024 * 1024, a); // allocator's alignment wins + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL1) { + #pragma omp atomic + err++; + printf("Error allocator: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL1); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + at[2].key = omp_atk_alignment; + at[2].value = AL0; + a = omp_init_allocator(omp_large_cap_mem_space, 3, at); + printf("allocator large aligned %d created: %p\n", AL0, (void *)a); + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_alloc(AL1, 1024 * 1024, a); // API's alignment wins + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL1) { + #pragma omp atomic + err++; + printf("Error param: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL1); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + + if (err == 0) { + printf("passed\n"); + return 0; + } else { + printf("failed\n"); + return 1; + } +} diff --git a/openmp/runtime/test/api/omp_aligned_calloc.c b/openmp/runtime/test/api/omp_aligned_calloc.c new file mode 100644 --- /dev/null +++ b/openmp/runtime/test/api/omp_aligned_calloc.c @@ -0,0 +1,85 @@ +// RUN: %libomp-compile-and-run +// UNSUPPORTED: gnu + +#include +#include +#include +#define NTH 8 +#define AL0 64 +#define AL1 128 + +int main() +{ + int err = 0; + omp_alloctrait_t at[3]; + omp_allocator_handle_t a; + void *p[NTH]; + at[0].key = omp_atk_pool_size; + at[0].value = 16*1024*1024; + at[1].key = omp_atk_fallback; + at[1].value = omp_atv_null_fb; + a = omp_init_allocator(omp_large_cap_mem_space, 2, at); + printf("allocator large created: %p\n", (void *)a); + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_calloc(AL0, 1024*128, 8, a); // API's alignment only + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL0) { + #pragma omp atomic + err++; + printf("Error param: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL0); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + at[2].key = omp_atk_alignment; + at[2].value = AL1; + a = omp_init_allocator(omp_large_cap_mem_space, 3, at); + printf("allocator large aligned %d created: %p\n", AL1, (void *)a); + if (a != omp_null_allocator) + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_calloc(AL0, 1024*128, 8, a); // allocator's alignment wins + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL1) { + #pragma omp atomic + err++; + printf("Error allocator: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL1); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + at[2].key = omp_atk_alignment; + at[2].value = AL0; + a = omp_init_allocator(omp_large_cap_mem_space, 3, at); + printf("allocator large aligned %d created: %p\n", AL0, (void *)a); + #pragma omp parallel num_threads(8) + { + int i = omp_get_thread_num(); + p[i] = omp_aligned_calloc(AL1, 1024*128, 8, a); // API's alignment wins + #pragma omp barrier + printf("th %d, ptr %p\n", i, p[i]); + if ((size_t)p[i] % AL1) { + #pragma omp atomic + err++; + printf("Error param: th %d, ptr %p is not %d-byte aligned\n", + i, p[i], AL1); + } + omp_free(p[i], a); + } + omp_destroy_allocator(a); + + if (err == 0) { + printf("passed\n"); + return 0; + } else { + printf("failed\n"); + return 1; + } +} diff --git a/openmp/runtime/tools/generate-def.pl b/openmp/runtime/tools/generate-def.pl --- a/openmp/runtime/tools/generate-def.pl +++ b/openmp/runtime/tools/generate-def.pl @@ -108,9 +108,10 @@ foreach my $entry ( keys( %$entries ) ) { if ( not $entries->{ $entry }->{ obsolete } ) { my $ordinal = $entries->{ $entry }->{ ordinal }; - # 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" ) { + # omp_alloc 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_free" and + $entry ne "omp_calloc" and $entry ne "omp_realloc" and + $entry ne "omp_aligned_alloc" and $entry ne "omp_aligned_calloc" ) { if ( not defined( $ordinal ) ) { runtime_error( "Bad entry \"$entry\": ordinal number is not specified."