diff --git a/libgomp/allocator.c b/libgomp/allocator.c index 9fcfc4ea5c6bb80d6013c6e80672af0abcdb3cf8..dce600f5bd7442334b9ff0690594753babea4fff 100644 --- a/libgomp/allocator.c +++ b/libgomp/allocator.c @@ -30,6 +30,7 @@ #define _GNU_SOURCE #include "libgomp.h" #include <stdlib.h> +#include <string.h> #define omp_max_predefined_alloc omp_thread_mem_alloc @@ -205,18 +206,19 @@ omp_destroy_allocator (omp_allocator_handle_t allocator) ialias (omp_init_allocator) ialias (omp_destroy_allocator) -static void * +void * omp_aligned_alloc (size_t alignment, size_t size, omp_allocator_handle_t allocator) { struct omp_allocator_data *allocator_data; - size_t new_size; + size_t new_size, new_alignment; void *ptr, *ret; if (__builtin_expect (size == 0, 0)) return NULL; retry: + new_alignment = alignment; if (allocator == omp_null_allocator) { struct gomp_thread *thr = gomp_thread (); @@ -228,19 +230,19 @@ retry: if (allocator > omp_max_predefined_alloc) { allocator_data = (struct omp_allocator_data *) allocator; - if (alignment < allocator_data->alignment) - alignment = allocator_data->alignment; + if (new_alignment < allocator_data->alignment) + new_alignment = allocator_data->alignment; } else { allocator_data = NULL; - if (alignment < sizeof (void *)) - alignment = sizeof (void *); + if (new_alignment < sizeof (void *)) + new_alignment = sizeof (void *); } new_size = sizeof (struct omp_mem_header); - if (alignment > sizeof (void *)) - new_size += alignment - sizeof (void *); + if (new_alignment > sizeof (void *)) + new_size += new_alignment - sizeof (void *); if (__builtin_add_overflow (size, new_size, &new_size)) goto fail; @@ -300,10 +302,11 @@ retry: goto fail; } - if (alignment > sizeof (void *)) + if (new_alignment > sizeof (void *)) ret = (void *) (((uintptr_t) ptr + sizeof (struct omp_mem_header) - + alignment - sizeof (void *)) & ~(alignment - 1)); + + new_alignment - sizeof (void *)) + & ~(new_alignment - 1)); else ret = (char *) ptr + sizeof (struct omp_mem_header); ((struct omp_mem_header *) ret)[-1].ptr = ptr; @@ -317,7 +320,7 @@ fail: switch (allocator_data->fallback) { case omp_atv_default_mem_fb: - if (alignment > sizeof (void *) + if ((new_alignment > sizeof (void *) && new_alignment > alignment) || (allocator_data && allocator_data->pool_size < ~(uintptr_t) 0)) { @@ -326,7 +329,7 @@ fail: } /* Otherwise, we've already performed default mem allocation and if that failed, it won't succeed again (unless it was - intermitent. Return NULL then, as that is the fallback. */ + intermittent. Return NULL then, as that is the fallback. */ break; case omp_atv_null_fb: break; @@ -342,10 +345,12 @@ fail: return NULL; } +ialias (omp_aligned_alloc) + void * omp_alloc (size_t size, omp_allocator_handle_t allocator) { - return omp_aligned_alloc (1, size, allocator); + return ialias_call (omp_aligned_alloc) (1, size, allocator); } /* Like omp_aligned_alloc, but apply on top of that: @@ -355,8 +360,9 @@ omp_alloc (size_t size, omp_allocator_handle_t allocator) void * GOMP_alloc (size_t alignment, size_t size, uintptr_t allocator) { - void *ret = omp_aligned_alloc (alignment, size, - (omp_allocator_handle_t) allocator); + void *ret + = ialias_call (omp_aligned_alloc) (alignment, size, + (omp_allocator_handle_t) allocator); if (__builtin_expect (ret == NULL, 0) && size) gomp_fatal ("Out of memory allocating %lu bytes", (unsigned long) size); @@ -396,5 +402,365 @@ ialias (omp_free) void GOMP_free (void *ptr, uintptr_t allocator) { - return omp_free (ptr, (omp_allocator_handle_t) allocator); + return ialias_call (omp_free) (ptr, (omp_allocator_handle_t) allocator); +} + +void * +omp_aligned_calloc (size_t alignment, size_t nmemb, size_t size, + omp_allocator_handle_t allocator) +{ + struct omp_allocator_data *allocator_data; + size_t new_size, size_temp, new_alignment; + void *ptr, *ret; + + if (__builtin_expect (size == 0 || nmemb == 0, 0)) + return NULL; + +retry: + new_alignment = alignment; + if (allocator == omp_null_allocator) + { + struct gomp_thread *thr = gomp_thread (); + if (thr->ts.def_allocator == omp_null_allocator) + thr->ts.def_allocator = gomp_def_allocator; + allocator = (omp_allocator_handle_t) thr->ts.def_allocator; + } + + if (allocator > omp_max_predefined_alloc) + { + allocator_data = (struct omp_allocator_data *) allocator; + if (new_alignment < allocator_data->alignment) + new_alignment = allocator_data->alignment; + } + else + { + allocator_data = NULL; + if (new_alignment < sizeof (void *)) + new_alignment = sizeof (void *); + } + + new_size = sizeof (struct omp_mem_header); + if (new_alignment > sizeof (void *)) + new_size += new_alignment - sizeof (void *); + if (__builtin_mul_overflow (size, nmemb, &size_temp)) + goto fail; + if (__builtin_add_overflow (size_temp, new_size, &new_size)) + goto fail; + + if (__builtin_expect (allocator_data + && allocator_data->pool_size < ~(uintptr_t) 0, 0)) + { + uintptr_t used_pool_size; + if (new_size > allocator_data->pool_size) + goto fail; +#ifdef HAVE_SYNC_BUILTINS + used_pool_size = __atomic_load_n (&allocator_data->used_pool_size, + MEMMODEL_RELAXED); + do + { + uintptr_t new_pool_size; + if (__builtin_add_overflow (used_pool_size, new_size, + &new_pool_size) + || new_pool_size > allocator_data->pool_size) + goto fail; + if (__atomic_compare_exchange_n (&allocator_data->used_pool_size, + &used_pool_size, new_pool_size, + true, MEMMODEL_RELAXED, + MEMMODEL_RELAXED)) + break; + } + while (1); +#else + gomp_mutex_lock (&allocator_data->lock); + if (__builtin_add_overflow (allocator_data->used_pool_size, new_size, + &used_pool_size) + || used_pool_size > allocator_data->pool_size) + { + gomp_mutex_unlock (&allocator_data->lock); + goto fail; + } + allocator_data->used_pool_size = used_pool_size; + gomp_mutex_unlock (&allocator_data->lock); +#endif + ptr = calloc (1, new_size); + if (ptr == NULL) + { +#ifdef HAVE_SYNC_BUILTINS + __atomic_add_fetch (&allocator_data->used_pool_size, -new_size, + MEMMODEL_RELAXED); +#else + gomp_mutex_lock (&allocator_data->lock); + allocator_data->used_pool_size -= new_size; + gomp_mutex_unlock (&allocator_data->lock); +#endif + goto fail; + } + } + else + { + ptr = calloc (1, new_size); + if (ptr == NULL) + goto fail; + } + + if (new_alignment > sizeof (void *)) + ret = (void *) (((uintptr_t) ptr + + sizeof (struct omp_mem_header) + + new_alignment - sizeof (void *)) + & ~(new_alignment - 1)); + else + ret = (char *) ptr + sizeof (struct omp_mem_header); + ((struct omp_mem_header *) ret)[-1].ptr = ptr; + ((struct omp_mem_header *) ret)[-1].size = new_size; + ((struct omp_mem_header *) ret)[-1].allocator = allocator; + return ret; + +fail: + if (allocator_data) + { + switch (allocator_data->fallback) + { + case omp_atv_default_mem_fb: + if ((new_alignment > sizeof (void *) && new_alignment > alignment) + || (allocator_data + && allocator_data->pool_size < ~(uintptr_t) 0)) + { + allocator = omp_default_mem_alloc; + goto retry; + } + /* Otherwise, we've already performed default mem allocation + and if that failed, it won't succeed again (unless it was + intermittent. Return NULL then, as that is the fallback. */ + break; + case omp_atv_null_fb: + break; + default: + case omp_atv_abort_fb: + gomp_fatal ("Out of memory allocating %lu bytes", + (unsigned long) (size * nmemb)); + case omp_atv_allocator_fb: + allocator = allocator_data->fb_data; + goto retry; + } + } + return NULL; +} + +ialias (omp_aligned_calloc) + +void * +omp_calloc (size_t nmemb, size_t size, omp_allocator_handle_t allocator) +{ + return ialias_call (omp_aligned_calloc) (1, nmemb, size, allocator); +} + +void * +omp_realloc (void *ptr, size_t size, omp_allocator_handle_t allocator, + omp_allocator_handle_t free_allocator) +{ + struct omp_allocator_data *allocator_data, *free_allocator_data; + size_t new_size, old_size, new_alignment, old_alignment; + void *new_ptr, *ret; + struct omp_mem_header *data; + + if (__builtin_expect (ptr == NULL, 0)) + return ialias_call (omp_aligned_alloc) (1, size, allocator); + + if (__builtin_expect (size == 0, 0)) + { + ialias_call (omp_free) (ptr, free_allocator); + return NULL; + } + + data = &((struct omp_mem_header *) ptr)[-1]; + free_allocator = data->allocator; + +retry: + new_alignment = sizeof (void *); + if (allocator == omp_null_allocator) + allocator = free_allocator; + + if (allocator > omp_max_predefined_alloc) + { + allocator_data = (struct omp_allocator_data *) allocator; + if (new_alignment < allocator_data->alignment) + new_alignment = allocator_data->alignment; + } + else + allocator_data = NULL; + if (free_allocator > omp_max_predefined_alloc) + free_allocator_data = (struct omp_allocator_data *) free_allocator; + else + free_allocator_data = NULL; + old_alignment = (uintptr_t) ptr - (uintptr_t) (data->ptr); + + new_size = sizeof (struct omp_mem_header); + if (new_alignment > sizeof (void *)) + new_size += new_alignment - sizeof (void *); + if (__builtin_add_overflow (size, new_size, &new_size)) + goto fail; + old_size = data->size; + + if (__builtin_expect (allocator_data + && allocator_data->pool_size < ~(uintptr_t) 0, 0)) + { + uintptr_t used_pool_size; + size_t prev_size = 0; + /* Check if we can use realloc. Don't use it if extra alignment + was used previously or newly, because realloc might return a pointer + with different alignment and then we'd need to memmove the data + again. */ + if (free_allocator_data + && free_allocator_data == allocator_data + && new_alignment == sizeof (void *) + && old_alignment == sizeof (struct omp_mem_header)) + prev_size = old_size; + if (new_size > prev_size + && new_size - prev_size > allocator_data->pool_size) + goto fail; +#ifdef HAVE_SYNC_BUILTINS + used_pool_size = __atomic_load_n (&allocator_data->used_pool_size, + MEMMODEL_RELAXED); + do + { + uintptr_t new_pool_size; + if (new_size > prev_size) + { + if (__builtin_add_overflow (used_pool_size, new_size - prev_size, + &new_pool_size) + || new_pool_size > allocator_data->pool_size) + goto fail; + } + else + new_pool_size = used_pool_size + new_size - prev_size; + if (__atomic_compare_exchange_n (&allocator_data->used_pool_size, + &used_pool_size, new_pool_size, + true, MEMMODEL_RELAXED, + MEMMODEL_RELAXED)) + break; + } + while (1); +#else + gomp_mutex_lock (&allocator_data->lock); + if (new_size > prev_size) + { + if (__builtin_add_overflow (allocator_data->used_pool_size, + new_size - prev_size, + &used_pool_size) + || used_pool_size > allocator_data->pool_size) + { + gomp_mutex_unlock (&allocator_data->lock); + goto fail; + } + } + else + used_pool_size = (allocator_data->used_pool_size + + new_size - prev_size); + allocator_data->used_pool_size = used_pool_size; + gomp_mutex_unlock (&allocator_data->lock); +#endif + if (prev_size) + new_ptr = realloc (data->ptr, new_size); + else + new_ptr = malloc (new_size); + if (new_ptr == NULL) + { +#ifdef HAVE_SYNC_BUILTINS + __atomic_add_fetch (&allocator_data->used_pool_size, + prev_size - new_size, + MEMMODEL_RELAXED); +#else + gomp_mutex_lock (&allocator_data->lock); + allocator_data->used_pool_size -= new_size - prev_size; + gomp_mutex_unlock (&allocator_data->lock); +#endif + goto fail; + } + else if (prev_size) + { + ret = (char *) new_ptr + sizeof (struct omp_mem_header); + ((struct omp_mem_header *) ret)[-1].ptr = new_ptr; + ((struct omp_mem_header *) ret)[-1].size = new_size; + ((struct omp_mem_header *) ret)[-1].allocator = allocator; + return ret; + } + } + else if (new_alignment == sizeof (void *) + && old_alignment == sizeof (struct omp_mem_header) + && (free_allocator_data == NULL + || free_allocator_data->pool_size == ~(uintptr_t) 0)) + { + new_ptr = realloc (data->ptr, new_size); + if (new_ptr == NULL) + goto fail; + ret = (char *) new_ptr + sizeof (struct omp_mem_header); + ((struct omp_mem_header *) ret)[-1].ptr = new_ptr; + ((struct omp_mem_header *) ret)[-1].size = new_size; + ((struct omp_mem_header *) ret)[-1].allocator = allocator; + return ret; + } + else + { + new_ptr = malloc (new_size); + if (new_ptr == NULL) + goto fail; + } + + if (new_alignment > sizeof (void *)) + ret = (void *) (((uintptr_t) new_ptr + + sizeof (struct omp_mem_header) + + new_alignment - sizeof (void *)) + & ~(new_alignment - 1)); + else + ret = (char *) new_ptr + sizeof (struct omp_mem_header); + ((struct omp_mem_header *) ret)[-1].ptr = new_ptr; + ((struct omp_mem_header *) ret)[-1].size = new_size; + ((struct omp_mem_header *) ret)[-1].allocator = allocator; + if (old_size - old_alignment < size) + size = old_size - old_alignment; + memcpy (ret, ptr, size); + if (__builtin_expect (free_allocator_data + && free_allocator_data->pool_size < ~(uintptr_t) 0, 0)) + { +#ifdef HAVE_SYNC_BUILTINS + __atomic_add_fetch (&free_allocator_data->used_pool_size, -data->size, + MEMMODEL_RELAXED); +#else + gomp_mutex_lock (&free_allocator_data->lock); + free_allocator_data->used_pool_size -= data->size; + gomp_mutex_unlock (&free_allocator_data->lock); +#endif + } + free (data->ptr); + return ret; + +fail: + if (allocator_data) + { + switch (allocator_data->fallback) + { + case omp_atv_default_mem_fb: + if (new_alignment > sizeof (void *) + || (allocator_data + && allocator_data->pool_size < ~(uintptr_t) 0)) + { + allocator = omp_default_mem_alloc; + goto retry; + } + /* Otherwise, we've already performed default mem allocation + and if that failed, it won't succeed again (unless it was + intermittent. Return NULL then, as that is the fallback. */ + break; + case omp_atv_null_fb: + break; + default: + case omp_atv_abort_fb: + gomp_fatal ("Out of memory allocating %lu bytes", + (unsigned long) size); + case omp_atv_allocator_fb: + allocator = allocator_data->fb_data; + goto retry; + } + } + return NULL; } diff --git a/libgomp/libgomp.map b/libgomp/libgomp.map index e0c813c2716d824d7bf0aa1c5694ad29e00fe585..460a7a4a34bee53f6c9e140ab690c5de374de0e3 100644 --- a/libgomp/libgomp.map +++ b/libgomp/libgomp.map @@ -203,6 +203,10 @@ OMP_5.0.2 { global: omp_get_device_num; omp_get_device_num_; + omp_aligned_alloc; + omp_calloc; + omp_aligned_calloc; + omp_realloc; } OMP_5.0.1; OMP_5.1 { diff --git a/libgomp/omp.h.in b/libgomp/omp.h.in index 314f964f8413d381c87953d4af54d552254d4468..e39988e7cbd34cc715c9c042c24533a1c44ec9e2 100644 --- a/libgomp/omp.h.in +++ b/libgomp/omp.h.in @@ -295,12 +295,31 @@ extern omp_allocator_handle_t omp_init_allocator (omp_memspace_handle_t, extern void omp_destroy_allocator (omp_allocator_handle_t) __GOMP_NOTHROW; extern void omp_set_default_allocator (omp_allocator_handle_t) __GOMP_NOTHROW; extern omp_allocator_handle_t omp_get_default_allocator (void) __GOMP_NOTHROW; -extern void *omp_alloc (__SIZE_TYPE__, - omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR) - __GOMP_NOTHROW __attribute__((__malloc__, __alloc_size__ (1))); extern void omp_free (void *, omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR) __GOMP_NOTHROW; +extern void *omp_alloc (__SIZE_TYPE__, + omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR) + __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free), + __alloc_size__ (1))); +extern void *omp_aligned_alloc (__SIZE_TYPE__, __SIZE_TYPE__, + omp_allocator_handle_t + __GOMP_DEFAULT_NULL_ALLOCATOR) + __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free), + __alloc_size__ (2))); +extern void *omp_calloc (__SIZE_TYPE__, __SIZE_TYPE__, + omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR) + __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free), + __alloc_size__ (1, 2))); +extern void *omp_aligned_calloc (__SIZE_TYPE__, __SIZE_TYPE__, __SIZE_TYPE__, + omp_allocator_handle_t + __GOMP_DEFAULT_NULL_ALLOCATOR) + __GOMP_NOTHROW __attribute__((__malloc__, __malloc__ (omp_free), + __alloc_size__ (2, 3))); +extern void *omp_realloc (void *, __SIZE_TYPE__, + omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR, + omp_allocator_handle_t __GOMP_DEFAULT_NULL_ALLOCATOR) + __GOMP_NOTHROW __attribute__((__malloc__ (omp_free), __alloc_size__ (2))); extern void omp_display_env (int) __GOMP_NOTHROW; diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c index 841e1bcc201bad73844aaa98245a3cfeff09895c..67ba1cda083969c01559689090df182905c61c05 100644 --- a/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c +++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-4.c @@ -12,12 +12,30 @@ main () if (omp_alloc (0, omp_null_allocator) != NULL) abort (); + if (omp_aligned_alloc (64, 0, omp_null_allocator) != NULL) + abort (); + if (omp_calloc (0, 0, omp_null_allocator) != NULL + || omp_calloc (32, 0, omp_null_allocator) != NULL + || omp_calloc (0, 64, omp_null_allocator) != NULL) + abort (); + if (omp_aligned_calloc (32, 0, 0, omp_null_allocator) != NULL + || omp_aligned_calloc (64, 32, 0, omp_null_allocator) != NULL + || omp_aligned_calloc (16, 0, 64, omp_null_allocator) != NULL) + abort (); a = omp_init_allocator (omp_default_mem_space, 2, traits); if (a != omp_null_allocator) { if (omp_alloc (0, a) != NULL || omp_alloc (0, a) != NULL - || omp_alloc (0, a) != NULL) + || omp_alloc (0, a) != NULL + || omp_aligned_alloc (16, 0, a) != NULL + || omp_aligned_alloc (128, 0, a) != NULL + || omp_calloc (0, 0, a) != NULL + || omp_calloc (32, 0, a) != NULL + || omp_calloc (0, 64, a) != NULL + || omp_aligned_calloc (32, 0, 0, a) != NULL + || omp_aligned_calloc (64, 32, 0, a) != NULL + || omp_aligned_calloc (16, 0, 64, a) != NULL) abort (); omp_destroy_allocator (a); } diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c new file mode 100644 index 0000000000000000000000000000000000000000..8b4a489a92bdc469f479e55b495d499a3edd3962 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-5.c @@ -0,0 +1,159 @@ +#include <omp.h> +#include <stdint.h> +#include <stdlib.h> + +const omp_alloctrait_t traits2[] += { { omp_atk_alignment, 16 }, + { omp_atk_sync_hint, omp_atv_default }, + { omp_atk_access, omp_atv_default }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_default_mem_fb }, + { omp_atk_partition, omp_atv_environment } }; +omp_alloctrait_t traits3[] += { { omp_atk_sync_hint, omp_atv_uncontended }, + { omp_atk_alignment, 32 }, + { omp_atk_access, omp_atv_all }, + { omp_atk_pool_size, 512 }, + { omp_atk_fallback, omp_atv_allocator_fb }, + { omp_atk_fb_data, 0 }, + { omp_atk_partition, omp_atv_default } }; +const omp_alloctrait_t traits4[] += { { omp_atk_alignment, 128 }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_null_fb } }; + +int +main () +{ + int *volatile p = (int *) omp_aligned_alloc (sizeof (int), 3 * sizeof (int), omp_default_mem_alloc); + int *volatile q; + int *volatile r; + omp_alloctrait_t traits[3] + = { { omp_atk_alignment, 64 }, + { omp_atk_fallback, omp_atv_null_fb }, + { omp_atk_pool_size, 4096 } }; + omp_allocator_handle_t a, a2; + + if ((((uintptr_t) p) % __alignof (int)) != 0) + abort (); + p[0] = 1; + p[1] = 2; + p[2] = 3; + omp_free (p, omp_default_mem_alloc); + p = (int *) omp_aligned_alloc (2 * sizeof (int), 2 * sizeof (int), omp_default_mem_alloc); + if ((((uintptr_t) p) % (2 * sizeof (int))) != 0) + abort (); + p[0] = 1; + p[1] = 2; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (omp_default_mem_alloc); + p = (int *) omp_aligned_alloc (1, sizeof (int), omp_null_allocator); + if ((((uintptr_t) p) % __alignof (int)) != 0) + abort (); + p[0] = 3; + omp_free (p, omp_get_default_allocator ()); + + a = omp_init_allocator (omp_default_mem_space, 3, traits); + if (a == omp_null_allocator) + abort (); + p = (int *) omp_aligned_alloc (32, 3072, a); + if ((((uintptr_t) p) % 64) != 0) + abort (); + p[0] = 1; + p[3071 / sizeof (int)] = 2; + if (omp_aligned_alloc (8, 3072, a) != NULL) + abort (); + omp_free (p, a); + p = (int *) omp_aligned_alloc (128, 3072, a); + if ((((uintptr_t) p) % 128) != 0) + abort (); + p[0] = 3; + p[3071 / sizeof (int)] = 4; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (a); + if (omp_get_default_allocator () != a) + abort (); + p = (int *) omp_aligned_alloc (64, 3072, omp_null_allocator); + if (omp_aligned_alloc (8, 3072, omp_null_allocator) != NULL) + abort (); + omp_free (p, a); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits2) / sizeof (traits2[0]), + traits2); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + p = (int *) omp_aligned_alloc (4, 420, a2); + if ((((uintptr_t) p) % 32) != 0) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_aligned_alloc (8, 768, a2); + if ((((uintptr_t) q) % 16) != 0) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + r = (int *) omp_aligned_alloc (8, 512, a2); + if ((((uintptr_t) r) % 8) != 0) + abort (); + r[0] = 9; + r[511 / sizeof (int)] = 10; + omp_free (p, omp_null_allocator); + omp_free (q, a2); + omp_free (r, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits4) / sizeof (traits4[0]), + traits4); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + omp_set_default_allocator (a2); +#ifdef __cplusplus + p = static_cast <int *> (omp_aligned_alloc (4, 420)); +#else + p = (int *) omp_aligned_alloc (4, 420, omp_null_allocator); +#endif + if ((((uintptr_t) p) % 32) != 0) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_aligned_alloc (64, 768, omp_null_allocator); + if ((((uintptr_t) q) % 128) != 0) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + if (omp_aligned_alloc (8, 768, omp_null_allocator) != NULL) + abort (); +#ifdef __cplusplus + omp_free (p); + omp_free (q); + omp_free (NULL); +#else + omp_free (p, omp_null_allocator); + omp_free (q, omp_null_allocator); + omp_free (NULL, omp_null_allocator); +#endif + omp_free (NULL, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c new file mode 100644 index 0000000000000000000000000000000000000000..be571b7ecea6af8c863c95ca7ecd4ed94d45615e --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-6.c @@ -0,0 +1,58 @@ +#include <omp.h> +#include <stdint.h> +#include <stdlib.h> + +const omp_alloctrait_t traits[] += { { omp_atk_alignment, 16 }, + { omp_atk_sync_hint, omp_atv_default }, + { omp_atk_access, omp_atv_default }, + { omp_atk_fallback, omp_atv_default_mem_fb }, + { omp_atk_partition, omp_atv_environment } }; + +int +main () +{ + omp_allocator_handle_t a; + void *p, *q; + volatile size_t large_sz; + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits) / sizeof (traits[0]), + traits); + if (a == omp_null_allocator) + abort (); + p = omp_alloc (2048, a); + if ((((uintptr_t) p) % 16) != 0) + abort (); + large_sz = ~(size_t) 1023; + q = omp_alloc (large_sz, a); + if (q != NULL) + abort (); + q = omp_aligned_alloc (32, large_sz, a); + if (q != NULL) + abort (); + q = omp_calloc (large_sz / 4, 4, a); + if (q != NULL) + abort (); + q = omp_aligned_calloc (1, 2, large_sz / 2, a); + if (q != NULL) + abort (); + omp_free (p, a); + large_sz = ~(size_t) 0; + large_sz >>= 1; + large_sz += 1; + if (omp_calloc (2, large_sz, a) != NULL) + abort (); + if (omp_calloc (large_sz, 1024, a) != NULL) + abort (); + if (omp_calloc (large_sz, large_sz, a) != NULL) + abort (); + if (omp_aligned_calloc (16, 2, large_sz, a) != NULL) + abort (); + if (omp_aligned_calloc (32, large_sz, 1024, a) != NULL) + abort (); + if (omp_aligned_calloc (64, large_sz, large_sz, a) != NULL) + abort (); + omp_destroy_allocator (a); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c new file mode 100644 index 0000000000000000000000000000000000000000..d66e25ac7d61cca225e22fca54594c1750921c9e --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-7.c @@ -0,0 +1,182 @@ +#include <omp.h> +#include <stdint.h> +#include <stdlib.h> + +const omp_alloctrait_t traits2[] += { { omp_atk_alignment, 16 }, + { omp_atk_sync_hint, omp_atv_default }, + { omp_atk_access, omp_atv_default }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_default_mem_fb }, + { omp_atk_partition, omp_atv_environment } }; +omp_alloctrait_t traits3[] += { { omp_atk_sync_hint, omp_atv_uncontended }, + { omp_atk_alignment, 32 }, + { omp_atk_access, omp_atv_all }, + { omp_atk_pool_size, 512 }, + { omp_atk_fallback, omp_atv_allocator_fb }, + { omp_atk_fb_data, 0 }, + { omp_atk_partition, omp_atv_default } }; +const omp_alloctrait_t traits4[] += { { omp_atk_alignment, 128 }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_null_fb } }; + +int +main () +{ + int *volatile p = (int *) omp_calloc (3, sizeof (int), omp_default_mem_alloc); + int *volatile q; + int *volatile r; + int i; + omp_alloctrait_t traits[3] + = { { omp_atk_alignment, 64 }, + { omp_atk_fallback, omp_atv_null_fb }, + { omp_atk_pool_size, 4096 } }; + omp_allocator_handle_t a, a2; + + if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2]) + abort (); + p[0] = 1; + p[1] = 2; + p[2] = 3; + omp_free (p, omp_default_mem_alloc); + p = (int *) omp_calloc (2, sizeof (int), omp_default_mem_alloc); + if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1]) + abort (); + p[0] = 1; + p[1] = 2; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (omp_default_mem_alloc); + p = (int *) omp_calloc (1, sizeof (int), omp_null_allocator); + if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0]) + abort (); + p[0] = 3; + omp_free (p, omp_get_default_allocator ()); + + a = omp_init_allocator (omp_default_mem_space, 3, traits); + if (a == omp_null_allocator) + abort (); + p = (int *) omp_calloc (3, 1024, a); + if ((((uintptr_t) p) % 64) != 0) + abort (); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 1; + p[3071 / sizeof (int)] = 2; + if (omp_calloc (1024, 3, a) != NULL) + abort (); + omp_free (p, a); + p = (int *) omp_calloc (512, 6, a); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 3; + p[3071 / sizeof (int)] = 4; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (a); + if (omp_get_default_allocator () != a) + abort (); + p = (int *) omp_calloc (12, 256, omp_null_allocator); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + if (omp_calloc (128, 24, omp_null_allocator) != NULL) + abort (); + omp_free (p, a); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits2) / sizeof (traits2[0]), + traits2); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + p = (int *) omp_calloc (10, 42, a2); + for (i = 0; i < 420 / sizeof (int); i++) + if (p[i]) + abort (); + if ((((uintptr_t) p) % 32) != 0) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_calloc (24, 32, a2); + if ((((uintptr_t) q) % 16) != 0) + abort (); + for (i = 0; i < 768 / sizeof (int); i++) + if (q[i]) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + r = (int *) omp_calloc (128, 4, a2); + if ((((uintptr_t) r) % __alignof (int)) != 0) + abort (); + for (i = 0; i < 512 / sizeof (int); i++) + if (r[i]) + abort (); + r[0] = 9; + r[511 / sizeof (int)] = 10; + omp_free (p, omp_null_allocator); + omp_free (q, a2); + omp_free (r, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits4) / sizeof (traits4[0]), + traits4); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + omp_set_default_allocator (a2); +#ifdef __cplusplus + p = static_cast <int *> (omp_calloc (42, 10)); +#else + p = (int *) omp_calloc (42, 10, omp_null_allocator); +#endif + if ((((uintptr_t) p) % 32) != 0) + abort (); + for (i = 0; i < 420 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_calloc (32, 24, omp_null_allocator); + if ((((uintptr_t) q) % 128) != 0) + abort (); + for (i = 0; i < 768 / sizeof (int); i++) + if (q[i]) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + if (omp_calloc (24, 32, omp_null_allocator) != NULL) + abort (); +#ifdef __cplusplus + omp_free (p); + omp_free (q); + omp_free (NULL); +#else + omp_free (p, omp_null_allocator); + omp_free (q, omp_null_allocator); + omp_free (NULL, omp_null_allocator); +#endif + omp_free (NULL, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c new file mode 100644 index 0000000000000000000000000000000000000000..bd4e08a6f9182a3116e1f59e3a5ca5fbbe625cc5 --- /dev/null +++ b/libgomp/testsuite/libgomp.c-c++-common/alloc-8.c @@ -0,0 +1,184 @@ +#include <omp.h> +#include <stdint.h> +#include <stdlib.h> + +const omp_alloctrait_t traits2[] += { { omp_atk_alignment, 16 }, + { omp_atk_sync_hint, omp_atv_default }, + { omp_atk_access, omp_atv_default }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_default_mem_fb }, + { omp_atk_partition, omp_atv_environment } }; +omp_alloctrait_t traits3[] += { { omp_atk_sync_hint, omp_atv_uncontended }, + { omp_atk_alignment, 32 }, + { omp_atk_access, omp_atv_all }, + { omp_atk_pool_size, 512 }, + { omp_atk_fallback, omp_atv_allocator_fb }, + { omp_atk_fb_data, 0 }, + { omp_atk_partition, omp_atv_default } }; +const omp_alloctrait_t traits4[] += { { omp_atk_alignment, 128 }, + { omp_atk_pool_size, 1024 }, + { omp_atk_fallback, omp_atv_null_fb } }; + +int +main () +{ + int *volatile p = (int *) omp_aligned_calloc (sizeof (int), 3, sizeof (int), omp_default_mem_alloc); + int *volatile q; + int *volatile r; + int i; + omp_alloctrait_t traits[3] + = { { omp_atk_alignment, 64 }, + { omp_atk_fallback, omp_atv_null_fb }, + { omp_atk_pool_size, 4096 } }; + omp_allocator_handle_t a, a2; + + if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0] || p[1] || p[2]) + abort (); + p[0] = 1; + p[1] = 2; + p[2] = 3; + omp_free (p, omp_default_mem_alloc); + p = (int *) omp_aligned_calloc (2 * sizeof (int), 1, 2 * sizeof (int), omp_default_mem_alloc); + if ((((uintptr_t) p) % (2 * sizeof (int))) != 0 || p[0] || p[1]) + abort (); + p[0] = 1; + p[1] = 2; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (omp_default_mem_alloc); + p = (int *) omp_aligned_calloc (1, 1, sizeof (int), omp_null_allocator); + if ((((uintptr_t) p) % __alignof (int)) != 0 || p[0]) + abort (); + p[0] = 3; + omp_free (p, omp_get_default_allocator ()); + + a = omp_init_allocator (omp_default_mem_space, 3, traits); + if (a == omp_null_allocator) + abort (); + p = (int *) omp_aligned_calloc (32, 3, 1024, a); + if ((((uintptr_t) p) % 64) != 0) + abort (); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 1; + p[3071 / sizeof (int)] = 2; + if (omp_aligned_calloc (8, 192, 16, a) != NULL) + abort (); + omp_free (p, a); + p = (int *) omp_aligned_calloc (128, 6, 512, a); + if ((((uintptr_t) p) % 128) != 0) + abort (); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 3; + p[3071 / sizeof (int)] = 4; + omp_free (p, omp_null_allocator); + omp_set_default_allocator (a); + if (omp_get_default_allocator () != a) + abort (); + p = (int *) omp_aligned_calloc (64, 12, 256, omp_null_allocator); + for (i = 0; i < 3072 / sizeof (int); i++) + if (p[i]) + abort (); + if (omp_aligned_calloc (8, 128, 24, omp_null_allocator) != NULL) + abort (); + omp_free (p, a); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits2) / sizeof (traits2[0]), + traits2); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + p = (int *) omp_aligned_calloc (4, 5, 84, a2); + for (i = 0; i < 420 / sizeof (int); i++) + if (p[i]) + abort (); + if ((((uintptr_t) p) % 32) != 0) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_aligned_calloc (8, 24, 32, a2); + if ((((uintptr_t) q) % 16) != 0) + abort (); + for (i = 0; i < 768 / sizeof (int); i++) + if (q[i]) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + r = (int *) omp_aligned_calloc (8, 64, 8, a2); + if ((((uintptr_t) r) % 8) != 0) + abort (); + for (i = 0; i < 512 / sizeof (int); i++) + if (r[i]) + abort (); + r[0] = 9; + r[511 / sizeof (int)] = 10; + omp_free (p, omp_null_allocator); + omp_free (q, a2); + omp_free (r, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + + a = omp_init_allocator (omp_default_mem_space, + sizeof (traits4) / sizeof (traits4[0]), + traits4); + if (a == omp_null_allocator) + abort (); + if (traits3[5].key != omp_atk_fb_data) + abort (); + traits3[5].value = (uintptr_t) a; + a2 = omp_init_allocator (omp_default_mem_space, + sizeof (traits3) / sizeof (traits3[0]), + traits3); + if (a2 == omp_null_allocator) + abort (); + omp_set_default_allocator (a2); +#ifdef __cplusplus + p = static_cast <int *> (omp_aligned_calloc (4, 21, 20)); +#else + p = (int *) omp_aligned_calloc (4, 21, 20, omp_null_allocator); +#endif + if ((((uintptr_t) p) % 32) != 0) + abort (); + for (i = 0; i < 420 / sizeof (int); i++) + if (p[i]) + abort (); + p[0] = 5; + p[419 / sizeof (int)] = 6; + q = (int *) omp_aligned_calloc (64, 12, 64, omp_null_allocator); + if ((((uintptr_t) q) % 128) != 0) + abort (); + for (i = 0; i < 768 / sizeof (int); i++) + if (q[i]) + abort (); + q[0] = 7; + q[767 / sizeof (int)] = 8; + if (omp_aligned_calloc (8, 24, 32, omp_null_allocator) != NULL) + abort (); +#ifdef __cplusplus + omp_free (p); + omp_free (q); + omp_free (NULL); +#else + omp_free (p, omp_null_allocator); + omp_free (q, omp_null_allocator); + omp_free (NULL, omp_null_allocator); +#endif + omp_free (NULL, omp_null_allocator); + omp_destroy_allocator (a2); + omp_destroy_allocator (a); + return 0; +}