diff --git a/include/aws/common/allocator.h b/include/aws/common/allocator.h index 2ac20d364..3aa27b474 100644 --- a/include/aws/common/allocator.h +++ b/include/aws/common/allocator.h @@ -229,19 +229,16 @@ AWS_COMMON_API size_t aws_small_block_allocator_page_size_available(struct aws_allocator *sba_allocator); /* - * Create an aligned allocator with customized alignment. + * Create an aligned allocator with an explicit alignment. Always align the allocated buffer with the passed-in + * alignment value. */ AWS_COMMON_API -struct aws_allocator *aws_customized_aligned_allocator_new( - struct aws_allocator *allocator, - size_t customized_alignment); +struct aws_allocator *aws_explicit_aligned_allocator_new(size_t alignment); /* - * Destroys a customized aligned allocator instance and frees its memory to the parent allocator. The parent - * allocator will otherwise be unaffected. + * Destroys a customized aligned allocator instance and frees its memory. */ -AWS_COMMON_API -void aws_customized_aligned_allocator_destroy(struct aws_allocator *aligned_alloc); +void aws_explicit_aligned_allocator_destroy(struct aws_allocator *aligned_alloc); AWS_EXTERN_C_END AWS_POP_SANE_WARNING_LEVEL diff --git a/source/allocator.c b/source/allocator.c index 6c2bf70fe..8d9bacaa8 100644 --- a/source/allocator.c +++ b/source/allocator.c @@ -34,31 +34,28 @@ bool aws_allocator_is_valid(const struct aws_allocator *alloc) { return alloc && AWS_OBJECT_PTR_IS_READABLE(alloc) && alloc->mem_acquire && alloc->mem_release; } -struct aws_aligned_allocator_impl { - struct aws_allocator *allocator; - size_t alignment_size; -}; - static void *s_aligned_malloc(struct aws_allocator *allocator, size_t size) { - (void)allocator; - /* larger allocations should be aligned so that AVX and friends can avoid - * the extra preamble during unaligned versions of memcpy/memset on big buffers - * This will also accelerate hardware CRC and SHA on ARM chips - * - * 64 byte alignment for > page allocations on 64 bit systems - * 32 byte alignment for > page allocations on 32 bit systems - * 16 byte alignment for <= page allocations on 64 bit systems - * 8 byte alignment for <= page allocations on 32 bit systems - * - * We use PAGE_SIZE as the boundary because we are not aware of any allocations of - * this size or greater that are not data buffers. - * - * Unless there is a customized alignment size. - */ - size_t alignment = sizeof(void *) * (size > (size_t)PAGE_SIZE ? 8 : 2); - if (allocator->impl) { - struct aws_aligned_allocator_impl *impl = allocator->impl; - alignment = impl->alignment_size; + size_t alignment = 0; + if (allocator->impl != NULL) { + alignment = (size_t)allocator->impl; + } else { + /** + * For implicit alignment. + * larger allocations should be aligned so that AVX and friends can avoid + * the extra preamble during unaligned versions of memcpy/memset on big buffers + * This will also accelerate hardware CRC and SHA on ARM chips + * + * 64 byte alignment for > page allocations on 64 bit systems + * 32 byte alignment for > page allocations on 32 bit systems + * 16 byte alignment for <= page allocations on 64 bit systems + * 8 byte alignment for <= page allocations on 32 bit systems + * + * We use PAGE_SIZE as the boundary because we are not aware of any allocations of + * this size or greater that are not data buffers. + * + * Unless there is a customized alignment size. + */ + alignment = sizeof(void *) * (size > (size_t)PAGE_SIZE ? 8 : 2); } #if !defined(_WIN32) void *result = NULL; @@ -157,7 +154,7 @@ static void *s_non_aligned_calloc(struct aws_allocator *allocator, size_t num, s return mem; } -static struct aws_allocator default_allocator = { +static struct aws_allocator s_default_allocator = { .mem_acquire = s_non_aligned_malloc, .mem_release = s_non_aligned_free, .mem_realloc = s_non_aligned_realloc, @@ -165,10 +162,10 @@ static struct aws_allocator default_allocator = { }; struct aws_allocator *aws_default_allocator(void) { - return &default_allocator; + return &s_default_allocator; } -static struct aws_allocator aligned_allocator = { +static struct aws_allocator s_implicit_aligned_allocator = { .mem_acquire = s_aligned_malloc, .mem_release = s_aligned_free, .mem_realloc = s_aligned_realloc, @@ -176,12 +173,10 @@ static struct aws_allocator aligned_allocator = { }; struct aws_allocator *aws_aligned_allocator(void) { - return &aligned_allocator; + return &s_implicit_aligned_allocator; } -struct aws_allocator *aws_customized_aligned_allocator_new( - struct aws_allocator *allocator, - size_t customized_alignment) { +struct aws_allocator *aws_explicit_aligned_allocator_new(size_t customized_alignment) { if ((customized_alignment & (customized_alignment - 1)) != 0 || customized_alignment % sizeof(void *) != 0) { /** * the alignment must be a power of two and a multiple of sizeof(void *) @@ -189,37 +184,18 @@ struct aws_allocator *aws_customized_aligned_allocator_new( aws_raise_error(AWS_ERROR_INVALID_ARGUMENT); return NULL; } - - struct aws_aligned_allocator_impl *aligned_alloc_impl = NULL; struct aws_allocator *aligned_alloc = NULL; - aws_mem_acquire_many( - allocator, - 2, - &aligned_alloc_impl, - sizeof(struct aws_aligned_allocator_impl), - &aligned_alloc, - sizeof(struct aws_allocator)); - - AWS_ZERO_STRUCT(*aligned_alloc_impl); - AWS_ZERO_STRUCT(*aligned_alloc); - /* copy the template vtable */ - *aligned_alloc = aligned_allocator; - aligned_alloc->impl = aligned_alloc_impl; - aligned_alloc_impl->alignment_size = customized_alignment; - aligned_alloc_impl->allocator = allocator; + aws_mem_calloc(aws_default_allocator(), 1, sizeof(struct aws_allocator)); + *aligned_alloc = s_implicit_aligned_allocator; + aligned_alloc->impl = (void *)customized_alignment; return aligned_alloc; } -void aws_customized_aligned_allocator_destroy(struct aws_allocator *aligned_alloc) { +void aws_explicit_aligned_allocator_destroy(struct aws_allocator *aligned_alloc) { if (!aligned_alloc) { return; } - struct aws_aligned_allocator_impl *impl = aligned_alloc->impl; - if (!impl) { - return; - } - struct aws_allocator *allocator = impl->allocator; - aws_mem_release(allocator, impl); + aws_mem_release(aws_default_allocator(), aligned_alloc); } void *aws_mem_acquire(struct aws_allocator *allocator, size_t size) { diff --git a/tests/alloc_test.c b/tests/alloc_test.c index 433226928..5a7be0635 100644 --- a/tests/alloc_test.c +++ b/tests/alloc_test.c @@ -383,56 +383,59 @@ static int s_aligned_threaded_allocs_and_frees(struct aws_allocator *allocator, AWS_TEST_CASE(aligned_threaded_allocs_and_frees, s_aligned_threaded_allocs_and_frees) static int s_customized_aligned_sanitize(struct aws_allocator *allocator, void *ctx) { + (void)allocator; (void)ctx; - struct aws_allocator *aligned_alloc = aws_customized_aligned_allocator_new(allocator, 1); + struct aws_allocator *aligned_alloc = aws_explicit_aligned_allocator_new(1); ASSERT_NULL(aligned_alloc); ASSERT_UINT_EQUALS(aws_last_error(), AWS_ERROR_INVALID_ARGUMENT); - aligned_alloc = aws_customized_aligned_allocator_new(allocator, 3 * sizeof(void *)); + aligned_alloc = aws_explicit_aligned_allocator_new(3 * sizeof(void *)); ASSERT_NULL(aligned_alloc); ASSERT_UINT_EQUALS(aws_last_error(), AWS_ERROR_INVALID_ARGUMENT); size_t aligned_size = 1024; - aligned_alloc = aws_customized_aligned_allocator_new(allocator, aligned_size); + aligned_alloc = aws_explicit_aligned_allocator_new(aligned_size); ASSERT_NOT_NULL(aligned_alloc); void *test = aws_mem_acquire(aligned_alloc, sizeof(void *)); ASSERT_TRUE((uintptr_t)test % aligned_size == 0); aws_mem_release(aligned_alloc, test); - aws_customized_aligned_allocator_destroy(aligned_alloc); + aws_explicit_aligned_allocator_destroy(aligned_alloc); return 0; } AWS_TEST_CASE(customized_aligned_sanitize, s_customized_aligned_sanitize) static int s_customized_aligned_threaded_reallocs(struct aws_allocator *allocator, void *ctx) { + (void)allocator; (void)ctx; srand(15); - struct aws_allocator *aligned_alloc = aws_customized_aligned_allocator_new(allocator, 512); + struct aws_allocator *aligned_alloc = aws_explicit_aligned_allocator_new(512); struct aws_allocator *alloc = aws_mem_tracer_new(aligned_alloc, NULL, AWS_MEMTRACE_STACKS, 8); s_thread_test(alloc, s_threaded_realloc_worker, alloc); aws_mem_tracer_destroy(alloc); - aws_customized_aligned_allocator_destroy(aligned_alloc); + aws_explicit_aligned_allocator_destroy(aligned_alloc); return 0; } AWS_TEST_CASE(customized_aligned_threaded_reallocs, s_customized_aligned_threaded_reallocs) static int s_customized_aligned_threaded_allocs_and_frees(struct aws_allocator *allocator, void *ctx) { + (void)allocator; (void)ctx; srand(99); - struct aws_allocator *aligned_alloc = aws_customized_aligned_allocator_new(allocator, 512); + struct aws_allocator *aligned_alloc = aws_explicit_aligned_allocator_new(512); struct aws_allocator *alloc = aws_mem_tracer_new(aligned_alloc, NULL, AWS_MEMTRACE_STACKS, 8); s_thread_test(alloc, s_threaded_alloc_worker, alloc); aws_mem_tracer_destroy(alloc); - aws_customized_aligned_allocator_destroy(aligned_alloc); + aws_explicit_aligned_allocator_destroy(aligned_alloc); return 0; }