Aligned allocation routines added.
Fortran interfaces added for all allocation routines.
Differential Revision: https://reviews.llvm.org/D110923
__kmpc_set_default_allocator
__kmpc_get_default_allocator
__kmpc_alloc
+ __kmpc_aligned_alloc
__kmpc_calloc
__kmpc_realloc
__kmpc_free
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
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);
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
! ***
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
! ***
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;
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();
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;
} 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
} 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 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 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
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;
*((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);
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;
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;
}
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;
}
__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
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) {
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) {
--- /dev/null
+// RUN: %libomp-compile-and-run
+// UNSUPPORTED: gnu
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+#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;
+ }
+}
--- /dev/null
+// RUN: %libomp-compile-and-run
+// UNSUPPORTED: gnu
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <omp.h>
+#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;
+ }
+}
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."